Metadata-Version: 2.4
Name: regstatusnet
Version: 1.0.2
Summary: Per-cell TF activity inference with learned post-translational regulation detection from scRNA-seq
Author-email: Lin Jiaen <jiaenlin999@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Lin Jiaen
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/JiaenLin/RegStatusNet
Project-URL: Repository, https://github.com/JiaenLin/RegStatusNet
Project-URL: Preprint, https://doi.org/10.5281/zenodo.20470333
Keywords: scRNA-seq,transcription factors,VAE,GRN,bioinformatics,PTM
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch<3,>=2.1
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.10
Requires-Dist: pandas>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: scikit-learn>=1.3
Requires-Dist: matplotlib>=3.7
Requires-Dist: tqdm>=4.65
Requires-Dist: requests>=2.28
Requires-Dist: scanpy>=1.9
Requires-Dist: decoupler>=1.4
Requires-Dist: anndata>=0.9
Provides-Extra: viz
Requires-Dist: umap-learn>=0.5; extra == "viz"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: nbconvert; extra == "dev"
Requires-Dist: ipykernel; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=7.0; extra == "docs"
Requires-Dist: furo>=2024.1; extra == "docs"
Requires-Dist: nbsphinx>=0.9; extra == "docs"
Requires-Dist: myst-parser>=2.0; extra == "docs"
Requires-Dist: sphinx-copybutton>=0.5; extra == "docs"
Provides-Extra: all
Requires-Dist: regstatusnet[dev,docs,viz]; extra == "all"
Dynamic: license-file

# RegStatusNet

**GRN-constrained structured latent space for per-cell transcription factor activity inference — with learned post-translational regulation detection**

[![PyPI](https://img.shields.io/pypi/v/regstatusnet)](https://pypi.org/project/regstatusnet/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Zenodo](https://img.shields.io/badge/model-Zenodo%2010.5281%2Fzenodo.20470333-blue)](https://doi.org/10.5281/zenodo.20470333)

---

## What it does

RegStatusNet infers **per-cell transcription factor (TF) activity** from scRNA-seq data alone. Unlike linear methods (VIPER, decoupleR), it:

- Assigns each latent dimension to a **named TF** (not an abstract factor)
- Enforces **activator/repressor sign polarity** from DoRothEA as a hard architectural constraint
- Learns a per-TF parameter **α** that identifies which TFs are **post-translationally regulated** — without any PTM supervision
- Scales to **100k+ cells** with adversarial batch correction

**Key result:** α correctly assigns low values to 14/16 known PTM regulators (87.5% recall), including the NF-κB, JAK-STAT, FOXO, and TGF-β/SMAD families, independently confirmed by ATAC chromatin concordance (Spearman ρ=+0.468, p=5.3×10⁻³).

---

## Quickstart (3 lines)

```python
import regstatusnet as rsn

model = rsn.Predictor.from_pretrained("pbmc_multiome_v1")   # downloads ~200 MB from Zenodo
z = model.transform(adata)                                   # (cells, 91) TF activity matrix
```

The pretrained PBMC model (`pbmc_multiome_v1`) is hosted at Zenodo:
**DOI: [10.5281/zenodo.20470333](https://doi.org/10.5281/zenodo.20470333)**

---

## Installation

```bash
pip install regstatusnet
```

Or clone for development:

```bash
git clone https://github.com/JiaenLin/RegStatusNet.git
cd RegStatusNet
pip install -e .
```

---

## Full API

```python
import regstatusnet as rsn

# Load from Zenodo (auto-downloads on first call)
model = rsn.Predictor.from_pretrained("pbmc_multiome_v1")

# Or from a local checkpoint
model = rsn.Predictor.from_pretrained("runs/my_model/best_model.pt")

# Run inference — auto gene alignment, handles missing genes
z = model.transform(adata, batch_size=512)       # (cells, 91) numpy array

# With uncertainty and α
out = model.transform(adata, return_dict=True)
# out["z"]      — (cells, 91) TF activity
# out["logvar"] — (cells, 91) uncertainty (log-variance)
# out["alpha"]  — (91,) per-TF α values (model property, not cell-specific)

# Interpret α
print(model.alpha_table())           # DataFrame: TF, alpha, tier
print(model.tf_names[:5])            # ['AR', 'ATF1', 'ATF2', ...]
```

---

## Pretrained model: pbmc_multiome_v1

| Property | Value |
|---|---|
| Training data | PBMC 10k Multiome (10x Genomics) |
| Cells | 11,620 |
| Cell types | 17 (CellTypist Immune_All_Low) |
| TFs | 91 (DoRothEA AB confidence) |
| GRN edges | 3,373 (95.4% activating) |
| Input genes | 3,257 (3,000 HVGs + 257 forced TF genes) |

**Validated benchmarks:**
- DoRothEA+viper: 78% of TFs r > 0.5, mean r = +0.641 (+0.44 above null)
- Perturb-seq specificity: top-5 hit rate 16.5% vs 5.5% chance (p=1.3×10⁻⁴)
- PTM recall: 87.5% (14/16 known PTM regulators assigned α < 0.05)
- ATAC chromatin validation: Spearman(α, ρ_atac) = +0.468, p=5.3×10⁻³

---

## Use cases

| Notebook | Description |
|---|---|
| [`docs/use_cases/pbmc_example.ipynb`](docs/use_cases/pbmc_example.ipynb) | Quickstart: load model, run inference, visualise |
| [`docs/use_cases/uc2_ifn_stimulation.ipynb`](docs/use_cases/uc2_ifn_stimulation.ipynb) | Apply to IFN-β stimulation data (Kang 2018) |
| [`docs/use_cases/uc3_ptm_discovery.ipynb`](docs/use_cases/uc3_ptm_discovery.ipynb) | Discover PTM-regulated TFs in your own PBMC data |

---

## Train on your own data

> **Data requirements:**
> - `adata.X` — raw integer counts (not log-normalized)
> - `adata.var_names` — HGNC gene symbols (e.g. `TP53`, not Ensembl IDs)
> - `adata.obs` — a column with cell-type labels (string)

**Option A — one-liner (sensible defaults):**
```python
import regstatusnet as rsn

ckpt = rsn.train("my_tissue.h5ad", label_col="cell_type", output_dir="runs/my_model")
model = rsn.Predictor.from_pretrained(str(ckpt))
z = model.transform(adata)   # (cells, n_tfs) TF activity
```

**Option B — programmatic config (no YAML needed):**
```python
import regstatusnet as rsn

cfg = rsn.get_default_config()
cfg["training"]["n_epochs"] = 150
cfg["data"]["n_hvgs"] = 4000          # increase for diverse tissues (brain, lung)
cfg["grn"]["confidence"] = "ABC"      # more TF-target edges

ckpt = rsn.train("brain.h5ad", config=cfg, output_dir="runs/brain_v1")
```

**Option C — CLI (after `pip install regstatusnet`):**
```bash
regstatusnet-train --h5ad my_tissue.h5ad --label_col cell_type --out runs/my_model

# More options
regstatusnet-train --h5ad brain.h5ad --out runs/brain_v1 \
    --label_col leiden --n_epochs 150 --n_hvgs 4000 \
    --confidence ABC
```

**Output:**
```
runs/my_model/
  best_model.pt   ← checkpoint with embedded gene names + config
  history.csv     ← per-epoch loss log
```

See [`docs/extending_to_new_tissues.md`](docs/extending_to_new_tissues.md) for tissue-specific hyperparameter guidance, GRN coverage checks, and validation against VIPER.

---

## Reproduce paper figures

```bash
# Generate Figures 2–5 (requires Stage 4 analysis CSVs from HPC)
bash scripts/make_figures.sh

# Generate Supplementary Figures S1–S2 (self-contained, no data needed)
python scripts/plot_supplementary.py --out_dir figures

# Generate Figure 1 UMAP (requires checkpoint + h5ad)
python scripts/plot_figure1_umap.py \
    --ckpt runs/stage2_multiome/best_model.pt \
    --h5ad data/pbmc10k_multiome.h5ad

# Generate Figure 1 A–C schematic (PowerPoint)
python scripts/make_figure1_schematic.py
```

---

## Docker

```bash
# Build image
docker-compose build

# CPU inference — mount your h5ad at /data and run a script
docker-compose run \
  -v /path/to/your/data:/data \
  regstatusnet python -c "
import regstatusnet as rsn
import scanpy as sc
adata = sc.read_h5ad('/data/your_pbmc.h5ad')
model = rsn.Predictor.from_pretrained('pbmc_multiome_v1')
z = model.transform(adata)
print('z shape:', z.shape)
"

# GPU inference — requires nvidia-container-toolkit
docker-compose run \
  -v /path/to/your/data:/data \
  regstatusnet-gpu python your_script.py

# Jupyter Lab (CPU) — open http://localhost:8888 after running
docker-compose up notebook
```

**Environment variables** (see `.env.example`):
- `REGSTATUSNET_CACHE` — override checkpoint cache directory
- `REGSTATUSNET_REF_H5AD` — path to reference h5ad (locally-trained models only)

> **Security note:** The notebook service disables the Jupyter token for ease of use.
> This is safe for local development but do not expose port 8888 on a public network.

---

## Citation

If you use RegStatusNet, please cite:

```bibtex
@software{lin2026regstatusnet,
  title   = {RegStatusNet: A GRN-constrained structured latent space identifies
             post-translationally regulated transcription factors from scRNA-seq},
  author  = {Lin, Jiaen},
  year    = {2026},
  doi     = {10.5281/zenodo.20470333},
  url     = {https://github.com/JiaenLin/RegStatusNet}
}
```

---

## License

[MIT](LICENSE) © 2026 Lin Jiaen
