Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 33 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
"customizations": {
"codespaces": {
"openFiles": [
"README.md",
"streamlit_app.py"
]
},
"vscode": {
"settings": {},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
]
}
},
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo '✅ Packages installed and Requirements met'",
"postAttachCommand": {
"server": "streamlit run streamlit_app.py --server.enableCORS false --server.enableXsrfProtection false"
},
"portsAttributes": {
"8501": {
"label": "Application",
"onAutoForward": "openPreview"
}
},
"forwardPorts": [
8501
]
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
## [1.2.1] - 2025-08-14
- Packaging: enrich pyproject metadata (authors, classifiers, dependencies, URLs) and set README content-type for PyPI

## [1.2.0] - 2025-08-14

- GUI: strategy-agnostic imputation panel (config-driven; per-column overrides; generic tuning)
- GUI: fix quality metrics picker defaults when config uses dict-style metrics
- Reporting: include categorical PSI/Cramér's V in bias warning header and per-row triggers
- Scripts: add clinical_all_features_e2e.py (full dataset/schema/config/custom mappings; online+offline runs)
- Fix: Python 3.9 compatibility in GUI typing; minor tuning UI improvements

## [1.1.1] - 2025-01-13

- feat: add class distribution bar chart to PDF and Markdown reports
- feat: persist per-file *_qc_summary.json with quality_scores, imputation, class_distribution
- fix: Python 3.9 typing compatibility in ImputationEngine (avoid PEP 604 unions)
- chore: docs and scripts updated to assert and document new artifact

## [1.1.0] - 2025-01-13

- feat: Optional class-distribution summary (label-aware)
- CLI: `--label-column`, `--imbalance-threshold`
- GUI: label column selector and threshold input
Expand All @@ -23,6 +29,7 @@
- PDF/MD: Imputation Settings and Tuning Summary sections
- fix: Redundancy metric deduplication (prefer identical over correlation)
- test: Added unit tests for class distribution, imputation params, tuning skeleton, and config load

# Changelog

All notable changes to PhenoQC will be documented in this file.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@ imputation:
Launch the Streamlit interface:

```bash
# Local
python run_gui.py

# Streamlit Community Cloud
# In the deploy UI, set the entrypoint to `streamlit_app.py`
```

Workflow:
Expand Down
45 changes: 43 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,51 @@ build-backend = "setuptools.build_meta"

[project]
name = "phenoqc"
version = "1.2.0"
version = "1.2.1"
requires-python = ">=3.9"
description = "Phenotypic Data Quality Control Toolkit for Genomic Data Infrastructure (GDI)"
readme = "README.md"
readme = { file = "README.md", content-type = "text/markdown" }
license = { file = "LICENSE" }
authors = [
{ name = "Jorge Miguel Ferreira da Silva" }
]
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Bio-Informatics",
]
dependencies = [
"pandas",
"jsonschema",
"requests",
"plotly",
"reportlab",
"streamlit",
"pyyaml",
"kaleido>=0.1.0",
"tqdm",
"Pillow",
"scikit-learn",
"fancyimpute",
"fastjsonschema",
"pronto",
"psutil",
"rapidfuzz",
"streamlit-aggrid",
"ucimlrepo",
]

[project.optional-dependencies]
test = ["pytest"]

[project.urls]
Homepage = "https://github.com/jorgeMFS/PhenoQC"
Repository = "https://github.com/jorgeMFS/PhenoQC.git"
Documentation = "https://phenoqc.readthedocs.io/en/latest/"
Issues = "https://github.com/jorgeMFS/PhenoQC/issues"

[project.scripts]
phenoqc = "phenoqc.cli:main"
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ psutil
rapidfuzz
streamlit-aggrid
ucimlrepo
watchdog
2 changes: 1 addition & 1 deletion src/phenoqc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "1.2.0"
__version__ = "1.2.1"

11 changes: 9 additions & 2 deletions src/phenoqc/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -942,8 +942,15 @@ def _render_params(spec: dict, initial: Optional[dict] = None) -> dict:
# Protected columns
st.subheader("Protected columns (excluded from imputation/tuning)")
protected_defaults = st.session_state['config'].get('protected_columns', []) or []
protected_selected = st.multiselect("Select protected columns", options=all_columns, default=protected_defaults,
help="These columns are excluded from the imputation feature matrix and tuning.")
# Streamlit requires defaults to be a subset of options; sanitize to avoid errors when
# config contains columns not present in the current dataset (e.g., on first load).
safe_protected_defaults = [c for c in protected_defaults if c in (all_columns or [])]
protected_selected = st.multiselect(
"Select protected columns",
options=all_columns,
default=safe_protected_defaults,
help="These columns are excluded from the imputation feature matrix and tuning.",
)
st.session_state['config']['protected_columns'] = protected_selected

# Redundancy metric settings
Expand Down
30 changes: 30 additions & 0 deletions streamlit_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python3

"""
Streamlit entrypoint for Streamlit Community Cloud.

This module imports and runs the PhenoQC GUI without spawning a subprocess.
It adjusts sys.path so that `src/` is importable when deployed.
"""

import os
import sys


def main() -> None:
# Ensure `src/` is importable when running on Streamlit Cloud
project_root = os.path.dirname(os.path.abspath(__file__))
src_path = os.path.join(project_root, "src")
if src_path not in sys.path:
sys.path.insert(0, src_path)

# Import and run the GUI main
from phenoqc.gui import main as gui_main

gui_main()


if __name__ == "__main__":
main()