Metadata-Version: 2.4
Name: pybirewirex
Version: 0.1.8
Summary: Fast degree-preserving network rewiring — Python port of the BiRewire R package
Author-email: Lorenzo Nemati <lorenzo.nemati@sns.it>
License: GPL-3.0-or-later
Project-URL: Homepage, https://github.com/lorenzoamir/PyBiRewireX
Project-URL: Documentation, https://pybirewirex.readthedocs.io
Project-URL: Repository, https://github.com/lorenzoamir/PyBiRewireX
Project-URL: Bug Tracker, https://github.com/lorenzoamir/PyBiRewireX/issues
Project-URL: Changelog, https://github.com/lorenzoamir/PyBiRewireX/blob/main/CHANGELOG.md
Keywords: network,rewiring,bipartite,graph,null model,genomics,switching algorithm
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.23
Requires-Dist: scipy>=1.9
Requires-Dist: cffi>=1.0
Provides-Extra: graph
Requires-Dist: igraph>=0.10; extra == "graph"
Requires-Dist: networkx>=3.0; extra == "graph"
Provides-Extra: vis
Requires-Dist: matplotlib>=3.5; extra == "vis"
Requires-Dist: scikit-learn>=1.1; extra == "vis"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.5; extra == "dev"
Requires-Dist: cibuildwheel>=2.16; extra == "dev"
Requires-Dist: igraph>=0.10; extra == "dev"
Requires-Dist: networkx>=3.0; extra == "dev"
Requires-Dist: matplotlib>=3.5; extra == "dev"
Requires-Dist: scikit-learn>=1.1; extra == "dev"
Requires-Dist: jupyter>=1.0; extra == "dev"
Requires-Dist: notebook>=7.0; extra == "dev"
Requires-Dist: sphinx>=7.0; extra == "dev"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "dev"
Requires-Dist: nbsphinx>=0.9; extra == "dev"
Requires-Dist: myst-parser>=2.0; extra == "dev"
Requires-Dist: pandoc; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=7.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
Requires-Dist: nbsphinx>=0.9; extra == "docs"
Requires-Dist: myst-parser>=2.0; extra == "docs"
Requires-Dist: matplotlib>=3.5; extra == "docs"
Requires-Dist: scikit-learn>=1.1; extra == "docs"
Dynamic: license-file

# PyBiRewireX

[![PyPI](https://img.shields.io/pypi/v/pybirewirex)](https://pypi.org/project/pybirewirex/)
[![Python](https://img.shields.io/pypi/pyversions/pybirewirex)](https://pypi.org/project/pybirewirex/)
[![Tests](https://github.com/lorenzoamir/PyBiRewireX/actions/workflows/ci.yml/badge.svg)](https://github.com/lorenzoamir/PyBiRewireX/actions/workflows/ci.yml)
[![Docs](https://readthedocs.org/projects/pybirewirex/badge/?version=latest)](https://pybirewirex.readthedocs.io/en/latest/)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

Python port of the [BiRewire R package](https://bioconductor.org/packages/BiRewire/) —
fast degree-preserving network randomisation via the Switching Algorithm with NetworkX
and igraph support.

Given a binary network (bipartite or undirected), PyBiRewireX generates rewired
versions that are uniformly drawn from the space of all networks with the same
degree sequence. This null model can be used to test whether observed network 
properties are trivially explained by degree alone.

---

## Installation

```bash
pip install pybirewirex
```

With optional graph-object support (igraph / networkx):

```bash
pip install "pybirewirex[graph]"
```

**Requirements:** Python ≥ 3.10, a C compiler (for building the extension).
Pre-built wheels are available for Linux x86_64/aarch64, macOS x86_64/arm64,
and Windows x86_64.

---

## Quick start

```python
import numpy as np
import pybirewirex as pbr

# Any binary 2-D ndarray (bipartite incidence matrix)
matrix = (np.random.default_rng(0).random((100, 40)) < 0.2).astype(np.int16)

# Rewire — row and column sums preserved
rewired = pbr.rewire_bipartite(matrix, seed=42)

assert np.array_equal(matrix.sum(axis=1), rewired.sum(axis=1))  # row sums
assert np.array_equal(matrix.sum(axis=0), rewired.sum(axis=0))  # col sums
```

Undirected graphs work identically — pass a symmetric adjacency matrix:

```python
rewired_graph = pbr.rewire_undirected(adjacency, seed=42)
```

scipy sparse matrices, igraph graphs, and networkx graphs are accepted
transparently and returned in the same format.

---

## Convergence analysis

The analytical bound N gives the minimum number of switching steps needed to
reach the stationary distribution. `analysis_bipartite` tracks Jaccard
similarity at every `step` iterations across `n_networks` independent runs,
letting you verify that the chain has converged.

```python
result = pbr.analysis_bipartite(
    matrix,
    n_networks = 10,   # independent rewiring runs
    step       = 1000, # record Jaccard every 1 000 steps
    seed       = 0,
)

print(f"Analytical bound N = {result.N}")
print(f"Scores shape: {result.scores.shape}")  # (10, n_steps)
```

---

## R vignette — Python reproductions

The figures below reproduce the two main outputs from the BiRewire R package
vignette (`BiRewire.Rnw`), generated by `scripts/demo.py`.

### Analysis — `birewire.analysis.bipartite`

Jaccard similarity between the original network and its rewired snapshots,
sampled every `step` switching steps across `n_networks` independent runs.
The red line marks the analytical bound N.

**Original BiRewire (R):**

![R analysis figure](.github/images/r_analysis.png)

**PyBiRewireX (Python):**

![Python analysis figure](.github/images/demo_analysis.png)

### Monitoring — `birewire.visual.monitoring.bipartite`

t-SNE visualisation of the Markov chain underlying the Switching Algorithm.
Each point is a sampled network; colour encodes sampling order (blue = first,
red = last). At small step counts the chain moves slowly (tight clusters); at
`k = N` and beyond the samples are uniformly distributed (scattered cloud).

**Original BiRewire (R):**

![R monitoring figure](.github/images/r_monitoring.png)

**PyBiRewireX (Python):**

![Python monitoring figure](.github/images/demo_monitoring.png)

---

## API reference

| Function | Description |
|----------|-------------|
| `rewire_bipartite(matrix, ...)` | Rewire bipartite network, preserving row and column sums |
| `rewire_undirected(adjacency, ...)` | Rewire undirected graph, preserving degree sequence |
| `analysis_bipartite(matrix, ...)` | Convergence analysis for bipartite rewiring |
| `analysis_undirected(adjacency, ...)` | Convergence analysis for undirected rewiring |
| `AnalysisResult` | Dataclass: `.N` (bound), `.scores` (n_networks × n_steps), `.step` |

All rewiring functions share the same keyword arguments:

| Argument | Type | Default | Description |
|----------|------|---------|-------------|
| `max_iter` | `int \| "n"` | `"n"` | Switching steps; `"n"` auto-computes bound N |
| `accuracy` | `float` | `1e-5` | Target accuracy δ for bound formula |
| `exact` | `bool` | `False` | Use exact vs approximate bound formula |
| `verbose` | `bool` | `True` | Print progress to stderr |
| `seed` | `int \| None` | `None` | RNG seed (None = random) |

Full API docs at **[pybirewirex.readthedocs.io](https://pybirewirex.readthedocs.io)**. WORK IN PROGRES!!!

---

## Development

```bash
git clone https://github.com/lorenzoamir/PyBiRewire
cd PyBiRewire
pip install -e ".[dev]"
pytest            # run test suite
ruff check .      # lint
ruff format .     # format
```

Build the Jupyter tutorial notebook:

```bash
jupyter notebook notebooks/tutorial.ipynb
```

Build docs locally:

```bash
cd docs && make html
```

---

## Citation

If you use PyBiRewireX in published research, please cite the original BiRewire
paper:

Iorio, F., Bernardo-Faura, M., Gobbi, A., Cokelaer, T., Jurman, G. and Saez-Rodriguez, J., 
**Efficient randomization of biological networks while preserving functional characterization of individual nodes.**
_BMC Bioinformatics_, 17(1), p.542. (2016).
[http://doi.org/10.1186/s12859-016-1402-1](http://doi.org/10.1186/s12859-016-1402-1)

---

## License

GPL-3.0-or-later — see [LICENSE](LICENSE).
