Skip to content

P2GX/beacon-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Beacon API

A production-ready implementation of the GA4GH Beacon v2 API using FastAPI. This project provides a complete, idiomatic FastAPI structure with abstract service interfaces, making it easy to implement your own database backend.

Features

  • âś… Complete Beacon v2 API implementation with all standard endpoints
  • âś… Clean architecture with separation of concerns (models, services, API)
  • âś… Abstract service interfaces - plug in your own database implementation
  • âś… Type-safe with full Pydantic models and type hints
  • âś… Production-ready with Docker support and health checks
  • âś… CI/CD with GitHub Actions (linting, testing, Docker builds)
  • âś… Configuration using Pydantic Settings with environment variables
  • âś… Modern tooling - uv, ruff, black, mypy

Architecture

beacon-api/
├── src/beacon_api/
│   ├── api/                    # FastAPI routers and endpoints
│   │   ├── individuals.py      # Individuals endpoint
│   │   ├── biosamples.py       # Biosamples endpoint
│   │   ├── genomic_variations.py
│   │   ├── analyses.py
│   │   ├── cohorts.py
│   │   ├── datasets.py
│   │   ├── runs.py
│   │   ├── info.py             # Beacon info endpoint
│   │   └── dependencies.py     # Dependency injection
│   ├── models/                 # Pydantic models
│   │   ├── common.py           # Shared models
│   │   ├── request.py          # Request models
│   │   ├── response.py         # Response models
│   │   └── entities.py         # Entity models
│   ├── services/               # Service layer (interfaces)
│   │   └── base.py             # Abstract base classes
│   ├── core/                   # Core application logic
│   │   └── config.py           # Configuration management
│   └── main.py                 # FastAPI application
├── tests/                      # Test suite
├── Dockerfile                  # Docker configuration
├── pyproject.toml              # Project metadata and dependencies
└── .github/workflows/          # CI/CD pipelines

Quick Start

Prerequisites

  • Python 3.11 or 3.12
  • uv (recommended) or pip

Installation

  1. Clone the repository:
git clone https://github.com/yourusername/beacon-api.git
cd beacon-api
  1. Create a virtual environment and install dependencies:
# Using uv (recommended)
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
uv pip install -e ".[dev]"

# Or using pip
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
  1. Copy the example environment file and customize:
cp .env.example .env
# Edit .env with your configuration
  1. Run the development server:
uvicorn beacon_api.main:app --reload

The API will be available at:

Implementing Your Database

The skeleton provides abstract service interfaces that you need to implement for your database backend. Here's how:

1. Create Your Service Implementation

Create a new file src/beacon_api/services/implementations.py:

from typing import Optional
from beacon_api.services.base import IndividualService
from beacon_api.models.entities import Individual
from beacon_api.models.request import BeaconRequestBody, FilteringTerm

class MyIndividualService(IndividualService):
    def __init__(self, db_connection):
        self.db = db_connection

    async def get_by_id(self, individual_id: str) -> Optional[Individual]:
        # Query your database
        result = await self.db.query(
            "SELECT * FROM individuals WHERE id = ?", individual_id
        )
        if result:
            return Individual(**result)
        return None

    async def list(
        self,
        skip: int = 0,
        limit: int = 10,
        filters: Optional[list[FilteringTerm]] = None,
    ) -> list[Individual]:
        # Implement your pagination and filtering logic
        results = await self.db.query(
            "SELECT * FROM individuals LIMIT ? OFFSET ?", limit, skip
        )
        return [Individual(**r) for r in results]

    async def query(self, request_body: BeaconRequestBody) -> list[Individual]:
        # Implement complex query logic based on request_body
        pass

# Implement similar classes for other entities:
# - MyBiosampleService
# - MyGenomicVariationService
# - MyAnalysisService
# - MyCohortService
# - MyDatasetService
# - MyRunService

2. Override Dependencies

Update src/beacon_api/api/dependencies.py:

from beacon_api.services.implementations import MyIndividualService
from your_database import get_db_connection

def get_individual_service() -> IndividualService:
    db = get_db_connection()
    return MyIndividualService(db)

# Override other service dependencies similarly

3. Initialize Database in Lifespan

Update src/beacon_api/main.py:

@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    # Startup: Initialize your database
    await database.connect()
    yield
    # Shutdown: Cleanup
    await database.disconnect()

Configuration

All configuration is managed through environment variables using Pydantic Settings. See .env.example for available options.

Key configuration categories:

  • API Configuration: Version, environment
  • Beacon Information: ID, name, description, URLs
  • Organization Information: Name, contact details
  • Server Configuration: Host, port, logging
  • CORS Configuration: Allowed origins, methods, headers

Docker Deployment

Build the Docker image:

docker build -t beacon-api:latest .

Run the container:

docker run -p 8000:8000 \
  -e BEACON_ID=my.beacon \
  -e BEACON_NAME="My Beacon" \
  beacon-api:latest

Using Docker Compose:

version: '3.8'
services:
  beacon:
    build: .
    ports:
      - "8000:8000"
    environment:
      - BEACON_ID=my.beacon
      - BEACON_NAME=My Beacon
      - ENVIRONMENT=production
    env_file:
      - .env

Development

Code Quality

Format code with black:

black src/ tests/

Lint with ruff:

ruff check src/ tests/

Type check with mypy:

mypy src/

Testing

Run tests:

pytest

With coverage:

pytest --cov=src/beacon_api --cov-report=html

Pre-commit Hooks

Install pre-commit hooks:

pip install pre-commit
pre-commit install

API Endpoints

Info

  • GET /api/info - Get Beacon information

Individuals

  • GET /api/individuals - List all individuals
  • GET /api/individuals/{id} - Get individual by ID
  • POST /api/individuals - Query individuals with filters

Biosamples

  • GET /api/biosamples - List all biosamples
  • GET /api/biosamples/{id} - Get biosample by ID
  • POST /api/biosamples - Query biosamples with filters

Genomic Variations

  • GET /api/g_variants - List all genomic variations
  • GET /api/g_variants/{id} - Get genomic variation by ID
  • POST /api/g_variants - Query genomic variations

Other Entities

  • Analyses: /api/analyses
  • Cohorts: /api/cohorts
  • Datasets: /api/datasets
  • Runs: /api/runs

Query Granularity

All POST endpoints support different response granularities:

  • boolean: Returns only whether matches exist
  • count: Returns count of matches
  • record: Returns full matching records

Example query:

{
  "meta": {
    "requested_granularity": "count"
  },
  "query": {
    "assembly_id": "GRCh38",
    "reference_name": "1",
    "start": [100000],
    "end": [200000]
  },
  "filters": [
    {
      "type": "ontology",
      "id": "HP:0001250",
      "scope": "individuals"
    }
  ]
}

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

Apache License 2.0

Resources

Support

For questions or issues, please open an issue on GitHub.


Note: This is a skeleton implementation with abstract service interfaces. You must implement the service layer for your specific database backend before deploying to production.

About

A beacon fast api skeleton

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published