Metadata-Version: 2.4
Name: bioviz-kit
Version: 0.4.2
Summary: Framework-agnostic plotting utilities for biological and clinical data visualization
Author-email: Victoria Cheung <victoriakcheung@gmail.com>
License: MIT License
        
        Copyright (c) 2025 Victoria Cheung
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
        Acknowledgement: This project builds on work originally developed at
        Revolution Medicines.
        
Project-URL: Homepage, https://github.com/vic-cheung/bioviz-kit
Project-URL: Issue Tracker, https://github.com/vic-cheung/bioviz-kit/issues
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.0
Requires-Dist: matplotlib>=3.6
Requires-Dist: seaborn>=0.12
Requires-Dist: adjusttext>=0.8
Requires-Dist: loguru>=0.7
Requires-Dist: pydantic<3,>=1.10
Requires-Dist: ipykernel>=7.1.0
Requires-Dist: statsmodels>=0.14.6
Requires-Dist: lifelines>=0.29
Requires-Dist: numpy>=1.24
Provides-Extra: testing
Requires-Dist: pytest; extra == "testing"
Dynamic: license-file

# bioviz-kit

Framework-agnostic visualization library for publication-ready clinical and biological data plots.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![Documentation](https://readthedocs.org/projects/bioviz-kit/badge/?version=latest)](https://bioviz-kit.readthedocs.io/)

## Features

- **Publication-ready styling** – Clean, professional visualizations out of the box
- **Framework-agnostic** – Works with any data pipeline or analysis framework
- **Pydantic configurations** – Type-safe, validated configuration objects
- **Clinical & bioinformatics focused** – Specialized plot types for common analyses:
  - Kaplan-Meier survival curves with risk tables
  - Volcano plots for differential expression/enrichment
  - Oncoplots (mutation landscapes)
  - Forest plots for hazard ratios
  - Waterfall plots for tumor response
  - Grouped bar charts with confidence intervals
  - Distribution plots (histogram + boxplot)
  - Styled tables

## Installation

Install from PyPI:

```bash
pip install bioviz-kit
```

Or using `uv`:

```bash
uv install bioviz-kit
```

Or install in development mode:

```bash
git clone https://github.com/yourusername/bioviz-kit.git
cd bioviz-kit
pip install -e .
```

Or using `uv` in editable/development mode:

```bash
uv install -e .
```

## Requirements

- Python 3.11+
- pandas
- matplotlib
- pydantic
- lifelines (for KM plots)
- adjustText (for label placement)
- seaborn (optional, for some plot types)

## Quick Start

### Kaplan-Meier Survival Plots

```python
import pandas as pd
from bioviz.configs import KMPlotConfig
from bioviz.plots import KMPlotter

# Your survival data
df = pd.DataFrame({
    "time": [5, 10, 15, 8, 12, 20, 6, 14],
    "event": [1, 0, 1, 1, 0, 1, 1, 0],
    "arm": ["Treatment", "Treatment", "Treatment", "Treatment",
            "Control", "Control", "Control", "Control"],
})

# Configure the plot
config = KMPlotConfig(
    time_col="time",
    event_col="event",
    group_col="arm",
    title="Overall Survival by Treatment Arm",
    xlabel="Time (months)",
    ylabel="Survival Probability",
    show_risktable=True,
    show_pvalue=True,
    color_dict={"Treatment": "#009E73", "Control": "#D55E00"},
)

# Generate the plot
plotter = KMPlotter(df, config)
fig, ax, pval = plotter.plot(output_path="km_plot.pdf")
print(f"Log-rank p-value: {pval:.4f}")
```

### Volcano Plots

```python
from bioviz.configs import VolcanoConfig
from bioviz.plots import VolcanoPlotter

# Differential expression results
df = pd.DataFrame({
    "gene": ["TP53", "KRAS", "EGFR", "BRCA1", "MYC"],
    "log2fc": [2.5, -1.8, 0.3, 3.1, -2.2],
    "pvalue": [0.001, 0.01, 0.5, 0.0001, 0.005],
})

config = VolcanoConfig(
    x_col="log2fc",
    y_col="pvalue",
    label_col="gene",
    title="Differential Expression Analysis",
    y_col_thresh=0.05,
    abs_x_thresh=1.5,
)

plotter = VolcanoPlotter(df, config)
fig, ax = plotter.plot()
fig.savefig("volcano.pdf", bbox_inches="tight")
```

### Oncoplots

```python
from bioviz.configs import OncoplotConfig
from bioviz.plots import OncoPlotter

# Mutation data (long format)
df = pd.DataFrame({
    "sample": ["S1", "S1", "S2", "S2", "S3"],
    "gene": ["TP53", "KRAS", "TP53", "EGFR", "KRAS"],
    "variant_class": ["Missense", "Missense", "Nonsense", "Amplification", "Missense"],
})

config = OncoplotConfig(
    sample_col="sample",
    gene_col="gene",
    variant_col="variant_class",
    title="Mutation Landscape",
)

plotter = OncoPlotter(df, config)
fig, axes = plotter.plot()
fig.savefig("oncoplot.pdf", bbox_inches="tight")
```

### Forest Plots

```python
from bioviz.configs import ForestPlotConfig
from bioviz.plots import ForestPlotter

# Hazard ratio data
df = pd.DataFrame({
    "comparator": ["Age >= 65", "Male", "Stage III-IV", "ECOG 1"],
    "reference": ["Age < 65", "Female", "Stage I-II", "ECOG 0"],
    "hr": [1.45, 0.92, 2.10, 1.68],
    "ci_lower": [1.10, 0.72, 1.65, 1.25],
    "ci_upper": [1.91, 1.18, 2.67, 2.26],
    "p_value": [0.008, 0.52, 0.001, 0.001],
})

config = ForestPlotConfig(
    title="Multivariate Cox Regression",
    xlabel="Hazard Ratio (95% CI)",
)

plotter = ForestPlotter(df, config)
fig, ax = plotter.plot()
fig.savefig("forest.pdf", bbox_inches="tight")
```

### Grouped Bar Charts with CIs

```python
from bioviz.configs import GroupedBarConfig
from bioviz.plots import GroupedBarPlotter

# Create from proportions (computes Clopper-Pearson CIs automatically)
config = GroupedBarConfig(
    title="Response Rates by Treatment",
    xlabel="Response Rate (%)",
    orientation="horizontal",
    ci_method="clopper-pearson",
)

plotter = GroupedBarPlotter.from_proportions(
    category_list=["CR", "PR", "SD", "PD"],
    group_configs=[
        {"name": "Treatment", "k": {"CR": 15, "PR": 25, "SD": 30, "PD": 10}, "n": 80},
        {"name": "Control", "k": {"CR": 5, "PR": 15, "SD": 35, "PD": 25}, "n": 80},
    ],
    config=config,
)
fig, ax = plotter.plot()
```

## Architecture

bioviz-kit follows a consistent pattern across all plot types:

```
bioviz/
├── configs/           # Pydantic configuration classes
│   ├── km_cfg.py      # KMPlotConfig
│   ├── volcano_cfg.py # VolcanoConfig
│   └── ...
├── plots/             # Plotter classes
│   ├── km.py          # KMPlotter
│   ├── volcano.py     # VolcanoPlotter
│   └── ...
└── utils/             # Shared utilities
```

Each plot type has:

1. A **Config class** (e.g., `KMPlotConfig`) - Pydantic model with validated fields
2. A **Plotter class** (e.g., `KMPlotter`) - Takes data + config, produces matplotlib figure

## Configuration Philosophy

All configurations use Pydantic models with:

- **Type hints** for IDE autocompletion
- **Validation** to catch errors early
- **Defaults** that produce publication-ready output
- **Documentation** via field descriptions

Font sizes default to `None` to inherit from matplotlib's rcParams, making it easy
to apply global themes:

```python
import matplotlib.pyplot as plt

# Set global style
plt.rcParams.update({
    "font.size": 12,
    "axes.labelsize": 14,
    "axes.titlesize": 16,
})

# Now all bioviz plots will use these sizes by default
```

## Examples

See the [`examples/`](examples/) directory for complete, runnable examples:

- `minimal_bioviz_smoke.py` - Line plots, oncoplots, tables
- `oncoplot_example.py` - Detailed oncoplot customization
- `volcano_smoke.py` - Volcano plot variations
- `distribution_examples.py` - Histogram + boxplot combinations
- `km_survival_example.py` - Kaplan-Meier survival analysis

## Documentation

Full documentation is available at [bioviz-kit.readthedocs.io](https://bioviz-kit.readthedocs.io/).

## Integration with tm-modeling

bioviz-kit serves as the visualization backend for tm-modeling.
Users of tm-modeling can continue using the existing API (`KMPlotConfig`, `generate_km_plot_and_risk_table`)
while benefiting from bioviz-kit's improved rendering.

## License

bioviz-kit is released under the MIT License (c) 2025 Victoria Cheung.

## Acknowledgments

This package was spun out of internal tooling developed at Revolution Medicines.
Many thanks to the team there for allowing the code to be open sourced.
