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
22 changes: 22 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: tests

on:
push:
pull_request:

jobs:
unit:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Run standard-library tests
run: python -m unittest discover -s tests -v
- name: Check compilation
run: python -m compileall -q genopedia examples tests

6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ logs/
*.tmp
*~

# Genopedia local reports
genopedia-report.html
genopedia-comparison.html

# Data
data/
*.npy
Expand All @@ -107,4 +111,4 @@ data/

# Dotenv
.env.local
.env.*.local
.env.*.local
147 changes: 65 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,100 +1,83 @@
# Genopedia - Genomics Machine Learning Pipeline
# Genopedia

**Genopedia** is a genomics-focused machine learning pipeline for DNA/RNA sequence analysis, variant detection, and color-coded visualization.
Genopedia is an offline-first toolkit for inspecting DNA/RNA sequences and producing reproducible local reports. It is designed to run after download on a normal Python installation without TensorFlow, PyTorch, a database, or an internet connection.

## ✅ Core Features
The current release provides:

### Genomics Pipeline
- **Nucleotide color coding**: A=🔴, T=🟡, G=🟢, C=🔵, U=🟤
- **Data loaders**: FASTA, FASTQ, VCF
- **Sequence analysis**: GC content, motif finding, functional region detection
- **Variant detection**: SNPs, insertions/deletions, pathogenicity scoring
- **Visualization**: HTML/SVG color-coded sequences
- Streaming FASTA, FASTQ, VCF, VCF.GZ, and raw-sequence readers.
- Sequence validation, GC fraction, ambiguous-base counts, Phred summaries, and warnings.
- Overlapping motif search and transparent candidate-region heuristics.
- Sequence comparison with substitutions, insertions, deletions, and replacements.
- A deterministic dependency-free k-mer classifier.
- Self-contained HTML/SVG reports and JSON summaries.
- A research-only interpretation boundary: no diagnosis, treatment advice, or proposed DNA edits.

### ML Models
- DNA sequence classifier (basic k-mer model implemented)
- Variant pathogenicity prediction
- Gene function annotation
- Extensible architecture for deep learning models
PCR and sequencing instruments are vendor-specific. Genopedia accepts exported files by default and exposes a clean boundary for future vendor adapters; it does not pretend that generic software can control every PCR device without its model and communication protocol.

## 📦 Project Structure
## Quick start from a fresh download

Requirements: Python 3.10 or newer. The core runtime uses only the Python standard library.

```powershell
python -m genopedia demo --length 120 --output report.html --json-output report.json
```
genopedia/
├── src/
│ ├── genomics/ # Core genomics pipeline
│ ├── models/ # ML models
│ ├── api/ # FastAPI backend
│ └── utils/ # Utilities
├── notebooks/ # Jupyter notebooks
├── tests/ # Unit tests
├── examples/ # Demo scripts
├── docs/ # Documentation
└── requirements.txt

Open `report.html` locally. No server or deployment is required.

Analyze a file:

```powershell
python -m genopedia analyze sample.fasta --output sample-report.html --json-output sample.json
python -m genopedia analyze sample.fastq --output reads-report.html
python -m genopedia analyze variants.vcf.gz --output variants-report.html
```

The convenience launcher also works directly from the repository root:

```powershell
python run_genopedia.py demo
```

## 🚀 Quick Start
```bash
cd ~/Desktop/genopedia
pip install -r requirements.txt
## Development

# Run a demo
python examples/demo_genomics.py
Run the built-in test suite without installing pytest:

# Run tests
python -m pytest tests/
```powershell
python -m unittest discover -s tests -v
```

## 🔬 Testing
Tests cover:
- Data loading/generation
- Sequence analysis
- Variant detection
- Visualization utilities
Install the package in editable mode if you want the `genopedia` command:

```bash
python -m pytest tests/test_genomics.py -v
```powershell
python -m pip install -e .
genopedia demo
```

## 📊 Visualization
Generates HTML/SVG color-coded nucleotide sequences:
Optional integrations are intentionally isolated from the core:

```python
from src.genomics import GenomicsVisualizer
visualizer = GenomicsVisualizer()
dna_sequence = "ATGCCGTAG"
html_output = visualizer.generate_color_html(dna_sequence)
```powershell
python -m pip install -e .[bio] # Biopython helpers
python -m pip install -e .[ml] # NumPy/scikit-learn extensions
python -m pip install -e .[dev] # pytest, formatting, and lint tools
```

## 🌐 API (Planned)
FastAPI backend for:
- Sequence analysis endpoints
- Variant detection
- ML model inference
- WebSocket for real-time visualization

## 🔗 Cloud Dataset Access
No large files stored locally - access datasets via:
- **GRCh38**: https://www.ncbi.nlm.nih.gov/grc/human
- **1000 Genomes**: s3://1000genomes/
- **ClinVar**: ftp://ftp.ncbi.nlm.nih.gov/pub/clinvar/
- **Ensembl**: ftp://ftp.ensembl.org/pub/
- **dbSNP**: ftp://ftp.ncbi.nlm.nih.gov/snp/

## 🧬 Genomics Context
Based on:
- [ChatGPT conversation](https://chatgpt.com/share/6a2aba33-10d8-83ea-992e-a1798edd9493)
- [Qwen conversation](https://chat.qwen.ai/s/d7f76f3a-5459-45be-9e8f-2cce2bd72079)
- [Kimi conversation](https://www.kimi.com/share/19eb6e89-8c42-8704-8000-0000b9440601)

## 🔮 Future Enhancements
1. Deep learning-based variant pathogenicity prediction
2. Gene expression analysis
3. CRISPR target identification
4. Web dashboard with interactive visualization
5. Integration with real PCR machines

## 📜 License
MIT License - see [LICENSE](LICENSE) ```

---
© 2026 Genopedia Project | [GitHub](#)
## Coordinate and safety conventions

Sequence comparisons use zero-based positions. VCF positions remain one-based and are marked as such in variant metadata. Variant interpretations are `unknown` unless supplied evidence matches a supported evidence label. Candidate promoters and start codons are heuristics, not gene annotation.

Genopedia is intended for research and engineering workflows. Any clinical interpretation, laboratory action, or genetic intervention requires validated laboratory methods and qualified human review.

## Project layout

```text
genopedia/
├── genopedia/ # dependency-free package and CLI
├── examples/ # runnable example
├── tests/ # standard-library tests
├── pyproject.toml # install metadata and optional extras
└── run_genopedia.py # fresh-checkout launcher
```

## License

MIT. See [LICENSE](LICENSE).
28 changes: 14 additions & 14 deletions examples/demo_genomics.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""GenoProject - resume point."""
from GenoProject.src.genomics import GenomicsDataLoader, SequenceAnalyzer, GenomicsVisualizer
from GenoProject.src.models import DNAClassifier

loader = GenomicsDataLoader("data/genomics")
sequence = loader.generate_synthetic_dna(120)
analyzer = SequenceAnalyzer()
variants = analyzer.detect_variants("ATGCCGTAG", "ATGTCGTAG")
visualizer = GenomicsVisualizer()

print("[GenoProject] sequence:", sequence)
print("[GenoProject] variants:", [v.to_dict() for v in variants])
print("[GenoProject] html preview:")
print(visualizer.generate_color_html(sequence, 20))
"""Run the dependency-free Genopedia demonstration from a fresh checkout."""

from pathlib import Path
import sys


# Make ``python examples/demo_genomics.py`` work before editable installation.
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from genopedia.cli import main # noqa: E402


if __name__ == "__main__":
raise SystemExit(main(["demo", "--length", "120"]))
20 changes: 20 additions & 0 deletions genopedia/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Genopedia: lightweight, offline-first genomics analysis tools."""

from .core import (
FunctionalRegion,
QualityReport,
SequenceAnalyzer,
SequenceRecord,
Variant,
)

__all__ = [
"FunctionalRegion",
"QualityReport",
"SequenceAnalyzer",
"SequenceRecord",
"Variant",
]

__version__ = "0.2.0"

6 changes: 6 additions & 0 deletions genopedia/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .cli import main


if __name__ == "__main__":
raise SystemExit(main())

47 changes: 47 additions & 0 deletions genopedia/adapters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Vendor-neutral local adapters for exported instrument files."""

from __future__ import annotations

from pathlib import Path

from .io import InputData, read_input


SUPPORTED_SUFFIXES = frozenset(
{".fa", ".fasta", ".fna", ".fq", ".fastq", ".vcf", ".gz"}
)


class FileDropAdapter:
"""Read sequence exports placed in a local directory.

The adapter intentionally does not assume a PCR vendor, USB protocol, or
network service. A vendor-specific adapter can implement the same
``discover``/``read`` boundary later without changing analysis code.
"""

def __init__(self, directory: str | Path, recursive: bool = False) -> None:
self.directory = Path(directory).resolve()
self.recursive = recursive

def discover(self) -> list[Path]:
if not self.directory.is_dir():
raise FileNotFoundError(f"file-drop directory does not exist: {self.directory}")
candidates = self.directory.rglob("*") if self.recursive else self.directory.iterdir()
supported: list[Path] = []
for path in candidates:
if not path.is_file():
continue
name = path.name.lower()
if name.endswith((".fa", ".fasta", ".fna", ".fq", ".fastq", ".vcf", ".fa.gz", ".fasta.gz", ".fq.gz", ".fastq.gz", ".vcf.gz")):
supported.append(path)
return sorted(supported, key=lambda path: path.name.lower())

def read(self, path: str | Path, format: str = "auto") -> InputData:
source = Path(path).resolve()
try:
source.relative_to(self.directory)
except ValueError as error:
raise ValueError("file-drop adapter cannot read outside its configured directory") from error
return read_input(source, format=format)

Loading
Loading