biocabinet 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- biocabinet-0.1.0/LICENSE +21 -0
- biocabinet-0.1.0/MANIFEST.in +54 -0
- biocabinet-0.1.0/PKG-INFO +386 -0
- biocabinet-0.1.0/README.md +320 -0
- biocabinet-0.1.0/biocabinet.egg-info/PKG-INFO +386 -0
- biocabinet-0.1.0/biocabinet.egg-info/SOURCES.txt +69 -0
- biocabinet-0.1.0/biocabinet.egg-info/dependency_links.txt +1 -0
- biocabinet-0.1.0/biocabinet.egg-info/entry_points.txt +2 -0
- biocabinet-0.1.0/biocabinet.egg-info/requires.txt +51 -0
- biocabinet-0.1.0/biocabinet.egg-info/top_level.txt +1 -0
- biocabinet-0.1.0/pyproject.toml +118 -0
- biocabinet-0.1.0/requirements-dev.txt +5 -0
- biocabinet-0.1.0/requirements-llm.txt +5 -0
- biocabinet-0.1.0/requirements.txt +42 -0
- biocabinet-0.1.0/scripts/__init__.py +1 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/__init__.py +1 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/config.py +341 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/graph.py +119 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/graph_nodes.py +683 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/graph_state.py +74 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/make_test_fastq.py +95 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/nodes.py +1070 -0
- biocabinet-0.1.0/scripts/bulk_rnaseq/run_preprocessing.py +167 -0
- biocabinet-0.1.0/scripts/common/__init__.py +1 -0
- biocabinet-0.1.0/scripts/common/data_detect.py +253 -0
- biocabinet-0.1.0/scripts/common/node_result.py +13 -0
- biocabinet-0.1.0/scripts/enrichment/__init__.py +1 -0
- biocabinet-0.1.0/scripts/enrichment/config.py +173 -0
- biocabinet-0.1.0/scripts/enrichment/gnn_data.py +312 -0
- biocabinet-0.1.0/scripts/enrichment/gnn_model.py +148 -0
- biocabinet-0.1.0/scripts/enrichment/gnn_test.py +262 -0
- biocabinet-0.1.0/scripts/enrichment/gnn_train.py +442 -0
- biocabinet-0.1.0/scripts/enrichment/graph.py +101 -0
- biocabinet-0.1.0/scripts/enrichment/graph_nodes.py +257 -0
- biocabinet-0.1.0/scripts/enrichment/graph_state.py +46 -0
- biocabinet-0.1.0/scripts/enrichment/inference.py +272 -0
- biocabinet-0.1.0/scripts/enrichment/merge_pathway_embeddings.py +487 -0
- biocabinet-0.1.0/scripts/enrichment/nodes.py +254 -0
- biocabinet-0.1.0/scripts/enrichment/pathway_embed.py +652 -0
- biocabinet-0.1.0/scripts/enrichment/playfile.py +6 -0
- biocabinet-0.1.0/scripts/enrichment/precompute_esm.py +240 -0
- biocabinet-0.1.0/scripts/enrichment/reactome_embed.py +292 -0
- biocabinet-0.1.0/scripts/enrichment/test_chain_smoke.py +315 -0
- biocabinet-0.1.0/scripts/enrichment/utils.py +199 -0
- biocabinet-0.1.0/scripts/enrichment/wikipathways_embed.py +207 -0
- biocabinet-0.1.0/scripts/orchestrator.py +580 -0
- biocabinet-0.1.0/scripts/rag/__init__.py +6 -0
- biocabinet-0.1.0/scripts/rag/answerer.py +450 -0
- biocabinet-0.1.0/scripts/rag/artifact_reader.py +426 -0
- biocabinet-0.1.0/scripts/rag/augment.py +282 -0
- biocabinet-0.1.0/scripts/rag/build_index.py +328 -0
- biocabinet-0.1.0/scripts/rag/graph.py +192 -0
- biocabinet-0.1.0/scripts/rag/graph_nodes.py +297 -0
- biocabinet-0.1.0/scripts/rag/graph_state.py +40 -0
- biocabinet-0.1.0/scripts/rag/pipeline_context.py +406 -0
- biocabinet-0.1.0/scripts/rag/retriever.py +278 -0
- biocabinet-0.1.0/scripts/rag/tools.py +262 -0
- biocabinet-0.1.0/scripts/render_graphs.py +68 -0
- biocabinet-0.1.0/scripts/scrna/__init__.py +1 -0
- biocabinet-0.1.0/scripts/scrna/config.py +171 -0
- biocabinet-0.1.0/scripts/scrna/graph.py +289 -0
- biocabinet-0.1.0/scripts/scrna/graph_nodes.py +347 -0
- biocabinet-0.1.0/scripts/scrna/graph_state.py +31 -0
- biocabinet-0.1.0/scripts/scrna/nodes.py +1083 -0
- biocabinet-0.1.0/scripts/spatial/__init__.py +1 -0
- biocabinet-0.1.0/scripts/spatial/config.py +118 -0
- biocabinet-0.1.0/scripts/spatial/graph.py +45 -0
- biocabinet-0.1.0/scripts/spatial/graph_nodes.py +240 -0
- biocabinet-0.1.0/scripts/spatial/nodes.py +602 -0
- biocabinet-0.1.0/setup.cfg +4 -0
- biocabinet-0.1.0/tests/test_imports.py +32 -0
biocabinet-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ishita Jain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Files to include in the source distribution (sdist)
|
|
2
|
+
include LICENSE
|
|
3
|
+
include README.md
|
|
4
|
+
include pyproject.toml
|
|
5
|
+
include requirements*.txt
|
|
6
|
+
|
|
7
|
+
# Include all Python source under scripts/
|
|
8
|
+
recursive-include scripts *.py py.typed
|
|
9
|
+
|
|
10
|
+
# ── Exclude everything that is NOT source code ──────────────────────────────
|
|
11
|
+
|
|
12
|
+
# Runtime pipeline output directories (scRNA step dirs written to project root)
|
|
13
|
+
prune 00_load
|
|
14
|
+
prune 01_qc
|
|
15
|
+
prune 02_filter
|
|
16
|
+
prune 02_trimmed
|
|
17
|
+
prune 03_normalize
|
|
18
|
+
prune 03_bam
|
|
19
|
+
prune 04_pca
|
|
20
|
+
prune 04_counts
|
|
21
|
+
prune 05_cluster
|
|
22
|
+
prune 05_normalized
|
|
23
|
+
prune 06_markers
|
|
24
|
+
prune 07_trajectory
|
|
25
|
+
prune 09_benchmark
|
|
26
|
+
|
|
27
|
+
# Pipeline run artifacts
|
|
28
|
+
exclude pipeline_runs.sqlite
|
|
29
|
+
exclude pipeline_runs.sqlite-shm
|
|
30
|
+
exclude pipeline_runs.sqlite-wal
|
|
31
|
+
exclude preprocessing_run.json
|
|
32
|
+
exclude app.log
|
|
33
|
+
exclude *.log
|
|
34
|
+
prune runs
|
|
35
|
+
|
|
36
|
+
# Pre-trained model weights downloaded at runtime (not shipped in the wheel)
|
|
37
|
+
prune biobert_v1.1_pubmed_pytorch_model
|
|
38
|
+
exclude *.ckpt
|
|
39
|
+
|
|
40
|
+
# Data directory (binary files — too large; see data/README.md for download)
|
|
41
|
+
prune data
|
|
42
|
+
|
|
43
|
+
# Presentation / docs
|
|
44
|
+
prune docs
|
|
45
|
+
|
|
46
|
+
# Development environment
|
|
47
|
+
prune .venv
|
|
48
|
+
prune .venv-dev
|
|
49
|
+
exclude biocabinet.egg-info
|
|
50
|
+
|
|
51
|
+
# Test outputs / caches
|
|
52
|
+
prune __pycache__
|
|
53
|
+
prune .pytest_cache
|
|
54
|
+
prune .mypy_cache
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: biocabinet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agentic multi-modal transcriptomics pipeline powered by LangGraph
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/ishitajain9717/biocabinet
|
|
7
|
+
Project-URL: Source, https://github.com/ishitajain9717/biocabinet
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/ishitajain9717/biocabinet/issues
|
|
9
|
+
Keywords: rna-seq,bioinformatics,langgraph,llm,agent,differential-expression,single-cell,spatial-transcriptomics,gnn,rag,pathway-enrichment
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: langgraph>=1.1.9
|
|
23
|
+
Requires-Dist: langgraph-checkpoint-sqlite>=3.0
|
|
24
|
+
Requires-Dist: langchain-core>=0.1.0
|
|
25
|
+
Requires-Dist: numpy>=2.0
|
|
26
|
+
Requires-Dist: scipy>=1.13
|
|
27
|
+
Requires-Dist: pandas>=2.0
|
|
28
|
+
Requires-Dist: torch>=2.0
|
|
29
|
+
Requires-Dist: transformers>=4.40
|
|
30
|
+
Requires-Dist: pydeseq2>=0.4
|
|
31
|
+
Requires-Dist: scanpy>=1.10
|
|
32
|
+
Requires-Dist: mygene>=3.2
|
|
33
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
34
|
+
Requires-Dist: langsmith>=0.1
|
|
35
|
+
Requires-Dist: requests>=2.31
|
|
36
|
+
Requires-Dist: tenacity>=8.2
|
|
37
|
+
Provides-Extra: llm-openai
|
|
38
|
+
Requires-Dist: langchain-openai>=0.1; extra == "llm-openai"
|
|
39
|
+
Provides-Extra: llm-ollama
|
|
40
|
+
Requires-Dist: langchain-ollama>=0.1; extra == "llm-ollama"
|
|
41
|
+
Provides-Extra: llm
|
|
42
|
+
Requires-Dist: langchain-openai>=0.1; extra == "llm"
|
|
43
|
+
Requires-Dist: langchain-ollama>=0.1; extra == "llm"
|
|
44
|
+
Provides-Extra: gnn
|
|
45
|
+
Requires-Dist: torch-geometric>=2.5; extra == "gnn"
|
|
46
|
+
Requires-Dist: fair-esm>=2.0.0; extra == "gnn"
|
|
47
|
+
Provides-Extra: spatial
|
|
48
|
+
Requires-Dist: squidpy>=1.6; extra == "spatial"
|
|
49
|
+
Requires-Dist: harmonypy>=0.0.10; extra == "spatial"
|
|
50
|
+
Provides-Extra: trajectory
|
|
51
|
+
Requires-Dist: palantir>=1.3; extra == "trajectory"
|
|
52
|
+
Provides-Extra: full
|
|
53
|
+
Requires-Dist: langchain-openai>=0.1; extra == "full"
|
|
54
|
+
Requires-Dist: langchain-ollama>=0.1; extra == "full"
|
|
55
|
+
Requires-Dist: torch-geometric>=2.5; extra == "full"
|
|
56
|
+
Requires-Dist: fair-esm>=2.0.0; extra == "full"
|
|
57
|
+
Requires-Dist: squidpy>=1.6; extra == "full"
|
|
58
|
+
Requires-Dist: harmonypy>=0.0.10; extra == "full"
|
|
59
|
+
Requires-Dist: palantir>=1.3; extra == "full"
|
|
60
|
+
Provides-Extra: dev
|
|
61
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
62
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
63
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
64
|
+
Requires-Dist: jupyter>=1.0; extra == "dev"
|
|
65
|
+
Dynamic: license-file
|
|
66
|
+
|
|
67
|
+
# Biocabinet
|
|
68
|
+
|
|
69
|
+
[](https://pypi.org/project/biocabinet/)
|
|
70
|
+
[](https://pypi.org/project/biocabinet/)
|
|
71
|
+
[](LICENSE)
|
|
72
|
+
[](https://github.com/ishitajain9717/biocabinet)
|
|
73
|
+
|
|
74
|
+
An agentic transcriptomics analysis platform built on [LangGraph](https://github.com/langchain-ai/langgraph).
|
|
75
|
+
It orchestrates FastQC → trimming → alignment → quantification → normalisation → differential expression → GNN-based PPI enrichment, with an optional RAG layer that grounds LLM summaries in KEGG and Reactome pathway knowledge.
|
|
76
|
+
|
|
77
|
+
The pipeline is **agentic at the decision points, not just the prose**: an LLM (with deterministic guardrails) decides whether a sample passes FastQC, what Trimmomatic steps to apply, what experiment type an input directory contains, and — in the spatial pipeline — whether suspicious clusters are a real cell type or an imaging batch effect. Every LLM decision is validated against hard metrics and falls back to rule-based logic if the model is unavailable or unreliable.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Architecture
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
Orchestrator (LangGraph)
|
|
85
|
+
│
|
|
86
|
+
├── Bulk RNA-seq sub-pipeline
|
|
87
|
+
│ ├── FastQC → Trimmomatic → STAR → featureCounts
|
|
88
|
+
│ ├── Normalisation (TPM / FPKM / RPKM)
|
|
89
|
+
│ ├── Differential Expression (PyDESeq2)
|
|
90
|
+
│ └── Summarise ← RAG-augmented (Phase 4a)
|
|
91
|
+
│
|
|
92
|
+
├── scRNA-seq sub-pipeline
|
|
93
|
+
│ ├── Load (h5ad / 10x / pbmc3k)
|
|
94
|
+
│ ├── QC → Filter → Normalise → PCA
|
|
95
|
+
│ ├── Cluster (Leiden / UMAP)
|
|
96
|
+
│ └── Marker genes → Summarise ← RAG-augmented
|
|
97
|
+
│
|
|
98
|
+
├── Spatial (imaging) sub-pipeline (in development — Vizgen/MERSCOPE)
|
|
99
|
+
│ ├── Load (squidpy Vizgen cell tables)
|
|
100
|
+
│ ├── QC (blank-FDR, per-cell counts/volume, FOV outliers)
|
|
101
|
+
│ ├── Cluster (PCA → Leiden)
|
|
102
|
+
│ └── FOV-bias check ← agentic (metrics + LLM + Harmony correct/re-cluster loop)
|
|
103
|
+
│
|
|
104
|
+
├── Enrichment sub-pipeline (auto-chained after bulk)
|
|
105
|
+
│ ├── Load PPI graph (STRING / SHS27k)
|
|
106
|
+
│ ├── GNN training (GIN, BFS split)
|
|
107
|
+
│ ├── Evaluation (test1/2/3 buckets)
|
|
108
|
+
│ └── Inference → Summarise ← RAG-augmented
|
|
109
|
+
│
|
|
110
|
+
└── RAG Q&A session (Phase 4b — interactive, after final report)
|
|
111
|
+
└── Retriever → LLM synthesis → Citations
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Graph diagrams (Mermaid + PNG) live in `docs/`.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Installation
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git clone https://github.com/ishitajain9717/biocabinet.git
|
|
122
|
+
cd biocabinet
|
|
123
|
+
python -m venv .venv && source .venv/bin/activate
|
|
124
|
+
|
|
125
|
+
# Option A: editable install (recommended — registers the `rnaseq-agent` CLI)
|
|
126
|
+
pip install -e ".[llm]"
|
|
127
|
+
|
|
128
|
+
# Option B: plain requirements files
|
|
129
|
+
pip install -r requirements.txt -r requirements-llm.txt
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Python dependencies (all modalities)
|
|
133
|
+
|
|
134
|
+
Installed via `pip install -e ".[llm]"` from `pyproject.toml`. These are **imported in code** — no separate binary on `PATH`.
|
|
135
|
+
|
|
136
|
+
| Package | Used by | Role |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| `langgraph`, `langchain-core` | Orchestrator, all graphs | Agent workflow + state |
|
|
139
|
+
| `pandas`, `numpy`, `scipy` | Bulk, scRNA, enrichment | Tables and numerics |
|
|
140
|
+
| `pydeseq2` | Bulk | Differential expression (DESeq2) |
|
|
141
|
+
| `scanpy` | scRNA, Spatial | Load h5ad/10x, QC, normalize, PCA, cluster, markers |
|
|
142
|
+
| `squidpy` | Spatial | Read MERSCOPE/Vizgen cell tables into AnnData |
|
|
143
|
+
| `harmonypy` | Spatial | FOV batch correction in the bias-check loop |
|
|
144
|
+
| `python-dotenv` | All | Auto-load LLM config from `.env` |
|
|
145
|
+
| `torch`, `torch-geometric` | Enrichment | GNN training and inference |
|
|
146
|
+
| `transformers` | Enrichment, RAG | BioBERT pathway text embeddings |
|
|
147
|
+
| `fair-esm` | Enrichment | ESM-2 protein sequence embeddings |
|
|
148
|
+
| `mygene` | Bulk (DEG → enrichment) | ENSG → ENSP mapping |
|
|
149
|
+
| `requests`, `tenacity` | Enrichment (pathway build) | KEGG / Reactome / WikiPathways APIs |
|
|
150
|
+
| `langchain-openai`, `langchain-ollama` | Summarise, RAG (optional) | LLM summaries and Q&A |
|
|
151
|
+
|
|
152
|
+
scRNA clustering (Leiden / UMAP) runs inside Scanpy. If Leiden fails at runtime, install graph backends:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pip install leidenalg python-igraph
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Requirements by modality
|
|
161
|
+
|
|
162
|
+
### Bulk RNA-seq
|
|
163
|
+
|
|
164
|
+
**Workflow:** FASTQ → FastQC → **agentic QC gate** → **agentic trim gate** (LLM picks Trimmomatic steps from the FastQC report) → STAR → featureCounts → TPM/FPKM/RPKM → PyDESeq2 → summarise (+ RAG).
|
|
165
|
+
|
|
166
|
+
The QC gate lets the agent **drop a failing sample and continue** with the rest of the batch rather than aborting the run; the trim gate generates sample-specific Trimmomatic arguments, validated against the FastQC metrics before execution.
|
|
167
|
+
|
|
168
|
+
| Type | Requirement | Notes |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| **CLI on `PATH`** | [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) | QC | `brew install fastqc` |
|
|
171
|
+
| | [STAR](https://github.com/alexdobin/STAR) | Alignment | `brew install star` |
|
|
172
|
+
| | [featureCounts](https://subread.sourceforge.net/) (Subread) | Gene counts | `brew install subread` |
|
|
173
|
+
| | [Trimmomatic](http://www.usadellab.org/cms/?page=trimmomatic) | Adapter/quality trim | JAR + `java`; steps chosen by the agentic trim gate |
|
|
174
|
+
| | `java` | Runs Trimmomatic | Required only if trimming is enabled |
|
|
175
|
+
| **Python (`pip`)** | `pydeseq2`, `pandas`, `mygene` | DEG + pair export for enrichment | In `pyproject.toml` |
|
|
176
|
+
| **Reference data** | STAR genome index + GTF | Not in git | See [`data/README.md`](data/README.md) — GENCODE GRCh38 + `STAR --runMode genomeGenerate` |
|
|
177
|
+
| **Input** | Paired FASTQ + sample sheet | | Conditions for DESeq2 (≥2 per group) |
|
|
178
|
+
| **Optional** | LLM env vars | RAG-augmented summary | See [LLM configuration](#llm-configuration) |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### scRNA-seq
|
|
183
|
+
|
|
184
|
+
**Workflow:** Load (h5ad / 10x / pbmc3k) → QC metrics → filter → normalize → HVG → PCA → neighbors → Leiden → UMAP → marker genes → summarise (+ RAG).
|
|
185
|
+
|
|
186
|
+
| Type | Requirement | Notes |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| **CLI on `PATH`** | *(none)* | Entire pipeline is Scanpy in Python |
|
|
189
|
+
| **Python (`pip`)** | `scanpy`, `numpy`, `scipy`, `pandas` | Core analysis | In `pyproject.toml` |
|
|
190
|
+
| | `leidenalg`, `python-igraph` | Leiden clustering | Often needed; install if clustering errors |
|
|
191
|
+
| **Input** | `.h5ad`, 10x folder, or `pbmc3k` | | Set in `ScrnaConfig` / interactive prompts |
|
|
192
|
+
| **Optional** | `data/pbmc3k_raw.h5ad` | Cached demo data | Download via Scanpy; see `data/README.md` |
|
|
193
|
+
| **Optional** | LLM + RAG index | Marker-gene pathway context in summary | Build RAG index once; see RAG section |
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Spatial transcriptomics (imaging-based)
|
|
198
|
+
|
|
199
|
+
**Status:** in active development. The v1 scope targets **imaging-based** platforms — **MERSCOPE / Vizgen** — starting from the post-segmentation cell tables (segmentation is the user's responsibility). The node-level building blocks are implemented and tested; final assembly into the orchestrated LangGraph (`scripts/spatial/graph.py`) is still in progress, so the orchestrator currently routes spatial inputs to a stub.
|
|
200
|
+
|
|
201
|
+
**Planned workflow:** Load (squidpy Vizgen reader) → QC (blank-FDR, per-cell counts/genes/volume, FOV outliers) → normalize → cluster (PCA → Leiden) → **FOV-bias check** → annotation (CeLLama-style, reimplemented in Python) → summarise (+ RAG).
|
|
202
|
+
|
|
203
|
+
| Type | Requirement | Notes |
|
|
204
|
+
|---|---|---|
|
|
205
|
+
| **CLI on `PATH`** | *(none)* | Entire pipeline is Python |
|
|
206
|
+
| **Python (`pip`)** | `squidpy`, `scanpy`, `harmonypy` | Read tables, QC/cluster, batch correction | In `pyproject.toml` |
|
|
207
|
+
| | `leidenalg`, `python-igraph` | Leiden clustering | Install if clustering errors |
|
|
208
|
+
| **Input** | `*_cell_by_gene.csv` + `*_cell_metadata.csv` | MERSCOPE per-region exports | Auto-detected in the input dir |
|
|
209
|
+
| **Optional** | LLM env vars | Agentic FOV-bias adjudication | Deterministic rule fallback without LLM |
|
|
210
|
+
|
|
211
|
+
**The FOV-bias check** is the spatial pipeline's flagship agentic step. Imaging-based data is captured tile-by-tile (each tile = a *field of view*, FOV), and per-FOV imaging differences can split one real cell type into several clusters. The node:
|
|
212
|
+
|
|
213
|
+
1. Computes deterministic evidence — **iLISI** (do expression-neighbors mix across FOVs?), **Cramér's V** (is cluster identity explained by FOV?), and the **fraction of cells in FOV-pure clusters**.
|
|
214
|
+
2. Hands that evidence to an LLM, which returns `BATCH_EFFECT` / `BIOLOGY` / `UNCERTAIN` plus an action — with **guardrails** that override the model in both directions (never silently keep an obvious artifact, never over-correct clean biology) and a rule-based fallback.
|
|
215
|
+
3. If a batch effect is confirmed, runs **Harmony** correction on the FOV label, re-clusters, and **re-verifies** that the split actually collapsed before accepting the result.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### Enrichment (GNN-PPI)
|
|
220
|
+
|
|
221
|
+
**Workflow:** Load PPI graph + ESM-2 + pathway embeddings → train GIN (BFS split) → bucketed eval → inference on DEG pairs. Auto-chained after a successful bulk run from the orchestrator.
|
|
222
|
+
|
|
223
|
+
| Type | Requirement | Notes |
|
|
224
|
+
|---|---|---|
|
|
225
|
+
| **CLI on `PATH`** | *(none)* | Training and inference are PyTorch |
|
|
226
|
+
| **Python (`pip`)** | `torch`, `torch-geometric`, `transformers`, `fair-esm` | Model + embeddings | In `pyproject.toml` |
|
|
227
|
+
| **Reference data** | `data/ppi_SHS27k.tsv`, `data/esm2_embeddings_SHS27k.pt`, `data/pathway/06_pathway_embeddings_combined.pt` | SHS27k benchmark | See `data/README.md` |
|
|
228
|
+
| **Upstream** | Bulk DEG `deg_pairs.tsv` | Optional | Orchestrator passes path when bulk DEG ran |
|
|
229
|
+
| **Optional** | GPU (`device=cuda` / `mps`) | Faster training | Default config uses `auto` |
|
|
230
|
+
|
|
231
|
+
Pathway embedding build (one-time, before merge):
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
python -m scripts.enrichment.pathway_embed
|
|
235
|
+
python -m scripts.enrichment.reactome_embed
|
|
236
|
+
python -m scripts.enrichment.wikipathways_embed
|
|
237
|
+
python -m scripts.enrichment.merge_pathway_embeddings
|
|
238
|
+
python -m scripts.enrichment.precompute_esm
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### RAG (pathway Q&A)
|
|
244
|
+
|
|
245
|
+
**Workflow:** Build index once → retriever (BioBERT cosine search) → answerer (LLM + citations) → augment pipeline summaries (4a) → optional interactive chat after orchestrator (4b).
|
|
246
|
+
|
|
247
|
+
| Type | Requirement | Notes |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| **CLI on `PATH`** | *(none)* | Search and embed in Python |
|
|
250
|
+
| **Python (`pip`)** | `transformers`, `torch` | BioBERT at index build and query time | In `pyproject.toml` |
|
|
251
|
+
| | `langchain-openai` or `langchain-ollama` | Prose answers | Optional; deterministic fallback without LLM |
|
|
252
|
+
| **Reference data** | KEGG + Reactome text under `data/pathway/` | Source for `build_index` | Built by enrichment pathway scripts |
|
|
253
|
+
| **Generated** | `data/rag/docs.jsonl`, `embeddings.npy`, `gene_to_doc_ids.json` | Local library | Not committed; run `build_index` |
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
python -m scripts.rag.build_index # once, after pathway data exists
|
|
257
|
+
python -m scripts.rag.retriever "cell cycle CDK4" # smoke-test retrieval
|
|
258
|
+
python -m scripts.rag.graph # interactive Q&A
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Bulk runs can set **pathway interests** at config time (e.g. `cell cycle, apoptosis`); matching DEGs are always included in RAG gene selection before the top-60% rule.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### Orchestrator
|
|
266
|
+
|
|
267
|
+
| Type | Requirement | Notes |
|
|
268
|
+
|---|---|---|
|
|
269
|
+
| **Python (`pip`)** | All of the above for chosen modality | Lazy-imports child graphs |
|
|
270
|
+
| **Persistence** | `pipeline_runs.sqlite` | LangGraph `SqliteSaver`; created on first run |
|
|
271
|
+
| **LLM** | `OLLAMA_MODEL` or `OPENAI_API_KEY` | Final report + RAG chat; optional |
|
|
272
|
+
|
|
273
|
+
The orchestrator **auto-detects the modality** from the input path (FASTQ/sample-sheet → bulk, 10x/h5ad → scRNA, Vizgen CSVs or spatial-coordinate h5ad → spatial) via `scripts/common/data_detect.py`, shows the evidence, and asks for confirmation rather than presenting a blind menu. A confirmed `bulk_rnaseq` run chains bulk → enrichment (if bulk succeeds) → final report → optional RAG Q&A; `scrna` runs scRNA only, then report and optional RAG.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Data setup
|
|
278
|
+
|
|
279
|
+
See [`data/README.md`](data/README.md) for instructions on downloading the required reference files, PPI graph, and pre-computed embeddings.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Running
|
|
284
|
+
|
|
285
|
+
### Full orchestrated pipeline
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
python -m scripts.orchestrator
|
|
289
|
+
# resume a previous run
|
|
290
|
+
python -m scripts.orchestrator --thread-id orchestrator_20260520_094200
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Individual sub-pipelines
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# Bulk RNA-seq
|
|
297
|
+
python -m scripts.bulk_rnaseq.graph
|
|
298
|
+
|
|
299
|
+
# scRNA-seq
|
|
300
|
+
python -m scripts.scrna.graph
|
|
301
|
+
|
|
302
|
+
# Enrichment (GNN-PPI)
|
|
303
|
+
python -m scripts.enrichment.graph
|
|
304
|
+
|
|
305
|
+
# Build RAG index (run once)
|
|
306
|
+
python -m scripts.rag.build_index
|
|
307
|
+
|
|
308
|
+
# Interactive RAG Q&A
|
|
309
|
+
python -m scripts.rag.graph
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## LLM configuration
|
|
315
|
+
|
|
316
|
+
The pipeline uses an LLM for plain-English summaries and RAG-grounded answers.
|
|
317
|
+
Configure via environment variables — no API keys in code:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Option A: local Ollama (free, offline)
|
|
321
|
+
export OLLAMA_MODEL=llama3
|
|
322
|
+
|
|
323
|
+
# Option B: OpenAI
|
|
324
|
+
export OPENAI_API_KEY=sk-...
|
|
325
|
+
export OPENAI_MODEL=gpt-4o-mini # optional, default is gpt-4o-mini
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
These can also be placed in a `.env` file at the repo root — it is auto-loaded via `python-dotenv`. If neither provider is set, all summarise nodes **and every agentic gate** (FastQC, trimming, data-type detection, FOV-bias) fall back to deterministic rule-based logic.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Project layout
|
|
333
|
+
|
|
334
|
+
```
|
|
335
|
+
scripts/
|
|
336
|
+
├── orchestrator.py top-level LangGraph orchestrator
|
|
337
|
+
├── bulk_rnaseq/ bulk RNA-seq sub-pipeline
|
|
338
|
+
│ ├── config.py PreprocessingConfig dataclass + CLI prompts
|
|
339
|
+
│ ├── nodes.py core bioinformatics functions
|
|
340
|
+
│ ├── graph_nodes.py LangGraph wrapper nodes
|
|
341
|
+
│ ├── graph_state.py PipelineState TypedDict
|
|
342
|
+
│ └── graph.py graph builder
|
|
343
|
+
├── scrna/ scRNA-seq sub-pipeline (same structure)
|
|
344
|
+
├── spatial/ spatial (imaging / Vizgen) sub-pipeline — in development
|
|
345
|
+
│ ├── config.py SpatialConfig (Vizgen CSVs + QC thresholds)
|
|
346
|
+
│ ├── nodes.py load_vizgen, spatial_qc, clustering, fov_bias_check
|
|
347
|
+
│ ├── graph_nodes.py LLM FOV-bias adjudication + guardrails
|
|
348
|
+
│ └── graph.py graph builder (assembly in progress)
|
|
349
|
+
├── enrichment/ GNN-PPI enrichment sub-pipeline
|
|
350
|
+
│ ├── pathway_embed.py KEGG pathway embeddings (BioBERT)
|
|
351
|
+
│ ├── reactome_embed.py Reactome pathway embeddings
|
|
352
|
+
│ ├── wikipathways_embed.py WikiPathways embeddings
|
|
353
|
+
│ ├── merge_pathway_embeddings.py multi-source merge + dedup
|
|
354
|
+
│ ├── precompute_esm.py ESM-2 protein sequence embeddings
|
|
355
|
+
│ ├── gnn_data.py PPI graph + feature assembly
|
|
356
|
+
│ ├── gnn_model.py GIN model definition
|
|
357
|
+
│ ├── gnn_train.py training loop (BFS split)
|
|
358
|
+
│ ├── gnn_test.py bucketed evaluation (test1/2/3)
|
|
359
|
+
│ └── inference.py predict interactions for novel pairs
|
|
360
|
+
├── rag/ RAG layer
|
|
361
|
+
│ ├── build_index.py Phase 1 — build pathway document library
|
|
362
|
+
│ ├── retriever.py Phase 2 — cosine similarity search
|
|
363
|
+
│ ├── answerer.py Phase 3 — LLM synthesis with citations
|
|
364
|
+
│ ├── augment.py Phase 4a — auto-augment pipeline summaries
|
|
365
|
+
│ ├── graph_state.py Phase 4b — RagChatState
|
|
366
|
+
│ ├── artifact_reader.py scan a run dir for STAR/featureCounts/FastQC/DEG/GNN artifacts
|
|
367
|
+
│ ├── graph_nodes.py Phase 4b — chat loop nodes (+ LLM data-type inference)
|
|
368
|
+
│ └── graph.py Phase 4b — interactive Q&A graph
|
|
369
|
+
└── common/
|
|
370
|
+
├── node_result.py NodeResult dataclass (shared across pipelines)
|
|
371
|
+
└── data_detect.py auto-detect modality (bulk / scRNA / spatial) from a path
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Checkpointing and resumption
|
|
377
|
+
|
|
378
|
+
All pipeline state is persisted to `pipeline_runs.sqlite` via LangGraph's `SqliteSaver`.
|
|
379
|
+
If a run is interrupted, resume it by passing the printed `--thread-id`.
|
|
380
|
+
Child pipelines (bulk, enrichment) share the same checkpointer as the orchestrator, so partial child runs are also resumable.
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## License
|
|
385
|
+
|
|
386
|
+
MIT
|