Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
425e8b3
fix the threshold
amrukwa Jul 9, 2025
c760852
clean up the tree, update BINA
amrukwa Jul 9, 2025
8971ad1
remove vae traces
amrukwa Jul 9, 2025
a95e2fd
add gene2path and initial filtering
amrukwa Jul 9, 2025
2532203
remove the gmm
amrukwa Jul 10, 2025
4cb57d0
remove additional scripts
amrukwa Jul 10, 2025
7f19592
remove notebooks
amrukwa Jul 10, 2025
a190dda
remove prev gmm tests
amrukwa Jul 10, 2025
23cb91b
add r dependency and kmeans thr
amrukwa Jul 10, 2025
2bcbc26
update jasmine
amrukwa Jul 11, 2025
12597a3
fix stability issue
amrukwa Jul 11, 2025
713a7de
fix the dockerfiles and make compatible with R
amrukwa Jul 11, 2025
392f456
update workflow
amrukwa Jul 11, 2025
401b65e
add dpgmm
amrukwa Jul 17, 2025
376deee
update workflow
amrukwa Jul 17, 2025
44c6d32
add gmm thresholding
amrukwa Jul 17, 2025
ad3435d
format via black
amrukwa Jul 17, 2025
e16ccfb
add aucell
amrukwa Jul 17, 2025
55aee41
update dockerfiles
amrukwa Jul 19, 2025
12002b6
update dockers
amrukwa Jul 19, 2025
29c75f7
fix default list
amrukwa Jul 19, 2025
d1f7b41
add the initial design
amrukwa Jul 19, 2025
ce99f5e
prepare directory
amrukwa Jul 23, 2025
1fe6c78
add thr logic
amrukwa Jul 23, 2025
af7d2c0
add readme, uptade dockerfiles
amrukwa Jul 25, 2025
539ad94
update dependencies
amrukwa Aug 9, 2025
d74026a
update gsea call
amrukwa Aug 11, 2025
71f8264
update visualizations
amrukwa Aug 11, 2025
e3f4e57
add progress options
amrukwa Aug 11, 2025
4244d99
add app utils
amrukwa Aug 11, 2025
80eb107
add package metadata
amrukwa Aug 11, 2025
f082454
add progress callback
amrukwa Aug 11, 2025
ae5acb6
update gmm
amrukwa Aug 11, 2025
8134623
update plotting
amrukwa Aug 11, 2025
805f2a2
update gmm
amrukwa Aug 11, 2025
b878472
fix aucell
amrukwa Aug 11, 2025
0ba6cb5
update dependencies
amrukwa Aug 11, 2025
6e34366
add integration ensurance
amrukwa Aug 11, 2025
9612d8d
add progress callback
amrukwa Aug 11, 2025
2554478
update gsea, clean up r calls
amrukwa Aug 12, 2025
373db5d
update tests
amrukwa Aug 12, 2025
aa28142
add good upload tab
amrukwa Aug 12, 2025
c3f5377
fix plotting
amrukwa Aug 12, 2025
af8bce7
update readme
amrukwa Aug 12, 2025
d334a0b
update gsea and zscire
amrukwa Aug 12, 2025
0d5d0c5
update the app
amrukwa Aug 12, 2025
e821c60
update the name
amrukwa Aug 12, 2025
6d238a2
update readme
amrukwa Aug 12, 2025
b7b0ba0
update readme more or less
amrukwa Aug 12, 2025
068a257
update aucell thr
amrukwa Aug 14, 2025
de2fa83
update readme, improve code quality
amrukwa Aug 14, 2025
179f6e4
improve testing pipeline and add failsafes
amrukwa Aug 14, 2025
dc7eaba
update workflow
amrukwa Aug 14, 2025
3280f4a
update r executor
amrukwa Aug 15, 2025
5d36b51
add logos
amrukwa Aug 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 45 additions & 5 deletions .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v4
- name: Run unit tests
run: docker build . --file docker/unittest.dockerfile --tag unittest
env:
Expand All @@ -16,15 +16,55 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up R 4.4.2
uses: r-lib/actions/setup-r@v2
with:
r-version: '4.4.2'
- name: Install R development packages
run: |
sudo apt-get update
sudo apt-get install -y \
r-base-dev \
libcurl4-openssl-dev \
libssl-dev \
libxml2-dev \
libgit2-dev \
libmagick++-dev
- name: Setup R packages using docker-compatible script
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_REMOTES_NO_ERRORS_FROM_WARNINGS: "true"
run: |
R -e "install.packages('remotes', repos='https://cran.r-project.org')"
Rscript setup_docker_compatible_renv.R
- name: Verify R packages installation
run: |
R -e "
essential_packages <- c('BiocManager', 'rjson', 'GSVA', 'dpGMM', 'AUCell')
cat('Verifying R packages installation:\\n')
all_ok <- TRUE
for (pkg in essential_packages) {
if (require(pkg, quietly = TRUE, character.only = TRUE)) {
cat(sprintf(' ✓ %s\\n', pkg))
} else {
cat(sprintf(' ✗ %s (MISSING)\\n', pkg))
all_ok <- FALSE
}
}
if (!all_ok) {
cat('Some packages are missing, this will cause test failures\\n')
quit(status = 1)
}
cat('All essential R packages verified successfully\\n')
"
- name: Install poetry
run: pipx install poetry

- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'poetry'
Expand Down
58 changes: 57 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ share/python-wheels/
*.egg
MANIFEST

# Build artifacts
build/*
dist/*
*.whl
*.tar.gz

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
Expand Down Expand Up @@ -134,4 +140,54 @@ dmypy.json
/data
/plots
/results
*.json
*.json

# R specific
renv/library/
renv/staging/
renv/local/
.Rproj.user
.Rhistory
.RData
.Ruserdata
*.Rproj

# Python environment
.venv/
venv/
.env
env/

# Testing and coverage
.pytest_cache/
.coverage
htmlcov/
.tox/
.nox/

# IDEs
.vscode/
.idea/
*.swp
*.swo
*~

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Temporary files
*.tmp
*.temp
*.log
*.out
*.err

# Docker
.docker/
Dockerfile.tmp
97 changes: 96 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,98 @@
# enrichment-auc
# pyFUNCellA
![Run unit tests](https://github.com/ZAEDPolSl/enrichment-auc/actions/workflows/unittest.yml/badge.svg)
[![CodeFactor](https://www.codefactor.io/repository/github/zaedpolsl/enrichment-auc/badge?s=0a2708157028b922c097a34ac955fe1c363866be)](https://www.codefactor.io/repository/github/zaedpolsl/enrichment-auc)

This repository is a Python implementation of the [FUNCellA R package](https://github.com/ZAEDPolSl/FUNCellA/tree/master).
You can use the original R version or run this Python version with the instructions below.

The presented package provides a wrapper solution for single-sample pathway enrichment algorithms. Additional functionality includes sample-level thresholding.

Implemented single-sample enrichment algorithms:
1) AUCell scoring (Aibar et al. 2017) - scRNA-Seq only
2) BINA (Zyla et al. 2025?) - scRNA-Seq only
3) CERNO AUC (Zyla et al. 2019)
4) JASMINE (Noureen et al. 2022) - scRNA-Seq only
5) Mean
6) ssGSEA (Barbie et al. 2009, Hänzelmann et al. 2013)
7) Z-score (Lee et al. 2008)

Implemented thresholding solutions:
1) AUCell package thresholding (Aibar et al. 2017)
2) k-means
3) GMM thresholding with Top 1 and k-means adjustment (Zyla et al. 2025?)

## Installation & Usage
The application is available [here](https://dssoftware.aei.polsl.pl/FUNCellA). It is free of charge and it does not store your data. Feel free to use it!
If you want to run it locally, there are several options:
### 🐳 Docker

#### 🚀 Quick Start - Run Pre-built App
```bash
# Pull and run the app directly (fastest option)
docker run -p 8501:8501 amrukwa/funcella:latest
```
The app will be available at **http://localhost:8501**

#### 🏗️ Build Locally with Cache (faster builds)
```bash
# Use cached builder for faster builds
docker build -f docker/streamlit.dockerfile --cache-from amrukwa/funcella:builder -t funcella .
docker run -p 8501:8501 funcella
```

#### 🔧 Build from Scratch
```bash
# Full build (slower, but completely from source)
docker build -f docker/streamlit.dockerfile -t funcella .
docker run -p 8501:8501 funcella
```

### 🛠️ Manual Installation

1. **R dependencies** (Required for GMM and AUCell thresholding)
```bash
# Recommended: Use the setup script for reliable installation
Rscript setup_docker_compatible_renv.R
```

**Alternative R setup methods:**
```R
# Option 1: Using renv (may require manual package fixes)
install.packages("renv")
renv::restore()

# Option 2: Manual installation
install.packages("BiocManager")
BiocManager::install("GSVA")
BiocManager::install("AUCell")
remotes::install_github("ZAEDPolSl/dpGMM")
```

**Note:** If you encounter GitHub authentication issues when installing dpGMM, the setup script handles this automatically by using alternative installation methods.

2. **Python dependencies**
```bash
# Install Poetry
curl -sSL https://install.python-poetry.org | python3 -

# Install dependencies
poetry install

# Run the app
streamlit run app.py
```

## 🔧 Troubleshooting

### R Package Issues
If you encounter errors related to missing R package dpGMM:
- The package will attempt automatic installation
- Alternatively, download and install manually from the repository environment.

## REFERENCES
Aibar, S., Bravo González-Blas, C., Moerman, T., Huynh-Thu, V.A., Imrichová, H., Hulselmans, G., Rambow, F., Marine, J.C., Geurts, P., Aerts, J., van den Oord, J., Kalender Atak, Z., Wouters, J., & Aerts, S (2017). SCENIC: Single-cell regulatory network inference and clustering. *Nature Methods*, *14*, 1083–1086.\
Barbie, D.A., Tamayo, P., Boehm, J.S., et al. (2009). Systematic RNA interference reveals that oncogenic KRAS-driven cancers require TBK1. *Nature*, *462*(7273), 108–112.\
Hänzelmann, S., Castelo, R., & Guinney, J. (2013). GSVA: gene set variation analysis for microarray and RNA-seq data. *BMC Bioinformatics*, *14*, 7.\
Lee, E., Chuang, H.Y., Kim, J.W., Ideker, T., & Lee, D. (2008). Inferring pathway activity toward precise disease classification. *PLoS Computational Biology*, *4*(11), e1000217.\
Noureen, N., Ye, Z., Chen, Y., Wang, X., & Zheng, S. (2022). Signature-scoring methods developed for bulk samples are not adequate for cancer single-cell RNA sequencing data. *Elife*, *11*, e71994.\
Zyla, J., Marczyk, M., Domaszewska, T., Kaufmann, S. H., Polanska, J., & Weiner III, J. (2019). Gene set enrichment for reproducible science: comparison of CERNO and eight other algorithms. *Bioinformatics*, *35*(24), 5146–5154.
21 changes: 21 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import streamlit as st

st.set_page_config(page_title="FUNCellA", page_icon="🧬")

from app.pas_tab import pas_tab
from app.threshold_tab import threshold_tab
from app.upload_tab import upload_tab

st.title("FUNCellA (Functional Cell Analysis)")
st.write(
"Upload your data and genesets, choose method and filtering options, calculate PAS and thresholding."
)

tabs = st.tabs(["Upload Files", "PAS Calculation", "Thresholding"])

with tabs[0]:
upload_tab()
with tabs[1]:
pas_tab()
with tabs[2]:
threshold_tab()
1 change: 1 addition & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Makes app a package for import
File renamed without changes.
118 changes: 118 additions & 0 deletions app/pas_tab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import streamlit as st
from pyfuncella.gene2path import gene2path


def pas_tab():
st.header("Step 2: PAS Calculation")
method = st.selectbox(
"Select calculation method",
["CERNO", "MEAN", "BINA", "AUCELL", "JASMINE", "ZSCORE", "SSGSEA"],
index=0,
key="method_select",
)
filt_cov = st.slider(
"Minimum pathway coverage (filt_cov)", 0.0, 1.0, 0.0, 0.01, key="filt_cov"
)
filt_min = st.number_input(
"Minimum pathway size (filt_min)", min_value=0, value=15, key="filt_min"
)
filt_max = st.number_input(
"Maximum pathway size (filt_max)", min_value=1, value=500, key="filt_max"
)
variance_filter_threshold = st.slider(
"Variance filter threshold (fraction of genes to keep)",
0.0,
1.0,
0.0,
0.01,
key="variance_filter",
)
aucell_threshold = None
if method == "AUCELL":
aucell_threshold = st.slider(
"AUCELL threshold (fraction of top genes)",
0.0,
1.0,
0.05,
0.01,
key="aucell_thr",
)
type_option = None
if method == "JASMINE":
type_option = st.selectbox(
"JASMINE effect size type",
["oddsratio", "likelihood"],
index=0,
key="jasmine_type",
)

if st.button("Run PAS calculation", key="run_pas"):
import os
import tempfile

data = st.session_state.get("data")
genes = st.session_state.get("genes")
genesets = st.session_state.get("genesets")
if data is None or genesets is None or len(genesets) == 0:
st.error("Both data and genesets must be loaded and non-empty.")
st.stop()
if method == "SSGSEA":
tmp_dir = "tmp"
os.makedirs(tmp_dir, exist_ok=True)
kwargs = dict(
data=data,
genesets=genesets,
genes=genes,
method=method,
filt_cov=filt_cov,
filt_min=filt_min,
filt_max=filt_max,
variance_filter_threshold=(
variance_filter_threshold if variance_filter_threshold > 0 else None
),
)
if method == "AUCELL":
kwargs["aucell_threshold"] = (
aucell_threshold if aucell_threshold is not None else 0.05
)
if method == "JASMINE":
kwargs["type"] = type_option

# Execute analysis
if method in ["SSGSEA"]:
with st.status(f"Running {method} analysis...", expanded=True) as status:
try:
result = gene2path(**kwargs)
status.update(
label=f"{method} analysis completed!", state="complete"
)
st.session_state["pas_result"] = result
st.session_state["pas_method"] = method
st.success(
f"PAS calculation completed. Result shape: {result.shape}"
)
st.dataframe(result)
st.download_button(
"Download results as CSV",
result.to_csv(),
file_name=f"{method}_results.csv",
on_click="ignore",
)
except Exception as e:
status.update(label=f"{method} analysis failed", state="error")
st.error(f"Error running {method}: {e}")
else:
try:
result = gene2path(**kwargs)
st.session_state["pas_result"] = result
st.session_state["pas_method"] = method
st.success(f"PAS calculation completed. Result shape: {result.shape}")
st.dataframe(result)
st.download_button(
"Download results as CSV",
result.to_csv(),
file_name=f"{method}_results.csv",
on_click="ignore",
)
except Exception as e:
st.error(f"Error running {method}: {e}")
Binary file added app/static/EN-logo-poziome-rgb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading