Metadata-Version: 2.4
Name: fidapy
Version: 0.1.0
Summary: A package to handle and analyse data from the FIDA 1 instrument.
Author-email: Rasmus Krogh Norrild <rkrno@dtu.dk>
Maintainer-email: Rasmus Krogh Norrild <rkrno@dtu.dk>
License: MIT
Project-URL: Repository, https://gitlab.gbar.dtu.dk/dtu_biophysics/fidapy
Project-URL: Bug Tracker, https://gitlab.gbar.dtu.dk/dtu_biophysics/fidapy/-/issues
Keywords: data analysis,fida,flow induced dispersion analysis,microfluidics,data science
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.26.4
Requires-Dist: scipy>=1.14.0
Requires-Dist: pandas>=2.2.0
Requires-Dist: matplotlib>=3.8.0
Requires-Dist: openpyxl>=3.1.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: ipython; extra == "dev"
Requires-Dist: jupyter; extra == "dev"
Provides-Extra: analysis
Requires-Dist: seaborn>=0.13.0; extra == "analysis"
Requires-Dist: scikit-learn>=1.5.0; extra == "analysis"
Requires-Dist: scikit-image>=0.25.0; extra == "analysis"
Provides-Extra: fitting
Requires-Dist: lmfit>=1.3.0; extra == "fitting"
Requires-Dist: emcee>=3.1.0; extra == "fitting"
Requires-Dist: corner>=2.1.0; extra == "fitting"
Provides-Extra: all
Requires-Dist: fidapy[analysis,dev,fitting]; extra == "all"
Dynamic: license-file

# fidapy

A Python package for analyzing data from Flow-Induced Dispersion Analysis (FIDA) instruments. Supports Taylor Dispersion Analysis (TDA), Taylor Dispersion-Induced Phase Separation (TDIPS), and Capillary Flow Experiments (Capflex).

## Installation

```bash
pip install fidapy
```

Optional extras:

```bash
# Fitting libraries (lmfit, emcee, corner)
pip install "fidapy[fitting]"

# Analysis libraries (seaborn, scikit-learn, scikit-image)
pip install "fidapy[analysis]"
```

For development:

```bash
git clone https://gitlab.gbar.dtu.dk/dtu_biophysics/fidapy
cd fidapy
pip install -e ".[dev]"
```

## Quick Start

### TDA — hydrodynamic radius

```python
from fidapy import TDAData

data = TDAData(
    path='sample.txt',
    measurement_pressure=400e2,   # Pa
    capillary_temperature=25,     # °C
    analyte_components={'NaCl': 0.1},  # M
)

print(f"rH = {data.hydrodynamic_radius * 1e9:.2f} nm")
print(f"D  = {data.diffusion_coefficient:.2e} m²/s")
```

### Binding affinity — K_d from a titration series

```python
from fidapy.experiments.binding_experiment import BindingExperiment

exp = BindingExperiment(
    path='data/titration/',
    analyte_components={'NaCl': 0.1},
    measurement_pressure=400e2,
)

print(f"K_d = {exp.kd * 1e9:.2f} nM  (95% CI: "
      f"{exp.kd_95ci[0]*1e9:.2f}–{exp.kd_95ci[1]*1e9:.2f} nM)")
print(f"dG  = {exp.dG:.1f} ± {exp.dG_std:.1f} kJ/mol")
```

By default the Langmuir isotherm is used. For tight binders (K_d ≈ indicator concentration) swap to the quadratic model:

```python
from fidapy.fit_functions import quadratic_binding
exp.fit(model=quadratic_binding, indicator_concentration=1e-9)
```

### TDIPS — phase separation screen

```python
from fidapy.experiments.TDIPS_experiment import TDIPSExperiment

exp = TDIPSExperiment(
    path='data/screen/',
    filename_regex_function=my_parser,
    measurement_pressure=8e4,
    norm_conc=True,
)

df = exp.summary()     # DataFrame: one row per sample, LLPS metrics + buffer components
df.sort_values('llps_score', ascending=False)
```

`summary()` columns always present: `name`, `time`, `analyte_concentration`, `spike_num`, `spike_sum_prominences`, `mid_int`, `front_integral`, `llps_score`. Additional `analyte_*` / `indicator_*` columns are added for every buffer component extracted from filenames.

### CapFlex — droplet characterization

```python
from fidapy import CapflexData

data = CapflexData(
    path='sample.txt',
    measurement_pressure=4e4,
    capillary_temperature=20,
    indicator_components={'NaCl': 0.1},
)

print(f"Baseline fluorescence: {data.baseline_fluorescence:.3f}")
print(f"Detected droplets: {len(data.spikes[0])}")

spike_heights = data.spikes[1]['prominences']
spike_widths  = data.spikes[1]['widths'] / data.measurement_frequency  # s
```

## Experiment classes

The `TDIPSExperiment` and `BindingExperiment` classes extend the base `Experiment` to handle batch loading with experiment-specific parameters.

| Class | Data class | Key method |
|---|---|---|
| `Experiment` | any `FIDAData` subclass | base loader |
| `TDIPSExperiment` | `TDIPSData` | `summary()` → DataFrame |
| `BindingExperiment` | `TDAData` | `fit()`, `summary()` → dict |

For FidaNeo files with a sample map, the base `Experiment` class reads buffer compositions directly from instrument metadata:

```python
from fidapy.experiments import Experiment
from fidapy import TDIPSData

# sample_map.xlsx defines what is in each vial
exp = Experiment(
    path='data/experiment_folder/',
    sample_map_path='data/experiment_folder/sample_map.xlsx',
    data_object_class=TDIPSData,
)
```

The sample map Excel file needs two sheets (`Tray 1`, `Tray 2`). Each sheet has `Vial pos`, `Vial name`, and any number of component columns. `protein_concentration` is a special column used for signal normalization.

```
Vial pos    Vial name   NaCl    PEG4000   protein_concentration
1           A1
2           B1          0.5     2
3           C1                            0.000010
```

## Custom filename parsing

When buffer conditions are encoded in the filename rather than in FidaNeo metadata, provide a parser function:

```python
import re
from pathlib import Path

def my_parser(filename: str):
    """Return (indicator_components, analyte_components)."""
    indicator, analyte = {}, {}
    basename = Path(filename).name

    # Example: '120uM_TDP16_0mM_urea_100mM_NaCl-03-05-2025-13-19.txt'
    m = re.match(r'(\d+)uM_([A-Za-z0-9]+)_(.*?)-\d{2}-\d{2}-\d{4}', basename)
    if m:
        indicator['protein_concentration'] = float(m.group(1)) * 1e-6
        indicator['protein_name'] = m.group(2)
        # parse buffer section ...

    return indicator, analyte

data = TDIPSData(
    path='sample.txt',
    filename_regex_function=my_parser,
    measurement_pressure=5e4,
    capillary_length=0.5,
)
```

Titrant concentration for TDA/binding experiments is read from the filename brackets automatically: `[27 uM] protein_buffer-date.txt` → `data.analyte_concentration = 27e-6`.

## Viscosity calculations

Buffer viscosity is calculated automatically from `analyte_components` / `indicator_components`. It can also be called directly:

```python
from fidapy.viscosity import calculate_buffer_viscosity, list_compatible_components

visc, not_used = calculate_buffer_viscosity(
    components={'NaCl': 0.15, 'PEG4000': 5, 'urea': 1.0},
    temp=25,  # °C
)
print(f"η = {visc * 1e3:.3f} mPa·s")

# List all supported components
print(list_compatible_components())
```

Salts use the Laliberté (2007) correlation; PEG uses the Huggins equation (Kirinčič & Klofutar 1999); urea and GdmHCl use empirical correlations. Unrecognised components are returned in `not_used` with a warning.

## Binding models

`fit_functions.py` provides:

| Function | Use case |
|---|---|
| `langmuir_isotherm` | Simple 1:1 binding; `K_d` ≫ `[indicator]` |
| `quadratic_binding` | Tight binding; `K_d` ≈ `[indicator]` |
| `competitive_displacement` | Competitive assays (Wang 1995) |
| `observable_fast_exchange` | Weighted-average observable from populations |

All binding functions take `dG_diss` (kJ/mol) and return `[frac_unbound, frac_bound]`. `K_d = exp(-dG / RT)`.

## Requirements

- Python ≥ 3.11
- numpy ≥ 1.26.4
- scipy ≥ 1.14.0
- pandas ≥ 2.2.0
- matplotlib ≥ 3.8.0
- openpyxl ≥ 3.1.0

## License

MIT

## Citation

If you use fidapy in your research, please cite the upcoming paper. Reference will be added when available.

## Contact

Rasmus Krogh Norrild — rkrno@dtu.dk  
Repository: https://gitlab.gbar.dtu.dk/dtu_biophysics/fidapy  
Developed at the DTU Biophysics group.
