Metadata-Version: 2.4
Name: fyron
Version: 0.2.4
Summary: Fyron is an open-source Python toolkit for interoperable healthcare data and AI workflows. It provides unified access to FHIR data via REST APIs and relational (SQL-backed) FHIR servers, integrates DICOM imaging sources, and enables semantic exploration of clinical narratives using modern language models.
Project-URL: Homepage, https://github.com/bitsandflames/fyron
Project-URL: Repository, https://github.com/bitsandflames/fyron
Project-URL: Documentation, https://bitsandflames.github.io/fyron/
Author-email: Bits & Flames <hello@bitsandflames.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: DICOM,FHIR,LLM,NLP,clinical,healthcare
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: dicomweb-client<0.60.0,>=0.59.1
Requires-Dist: pandas<3.0.0,>=2.2.0
Requires-Dist: psycopg<4.0.0,>=3.1.19
Requires-Dist: pydicom<3.0.0,>=2.4.4
Requires-Dist: pyjwt<3.0.0,>=2.9.0
Requires-Dist: python-dotenv<2.0.0,>=1.0.1
Requires-Dist: requests<3.0.0,>=2.32.0
Requires-Dist: retrying<2.0.0,>=1.3.3
Requires-Dist: simpleitk<3.0.0,>=2.3.1
Requires-Dist: tqdm<5.0.0,>=4.66.0
Provides-Extra: audit
Provides-Extra: boruta
Requires-Dist: boruta<0.4.0,>=0.3.0; extra == 'boruta'
Provides-Extra: descriptive
Requires-Dist: numpy<2.0.0,>=1.26.0; extra == 'descriptive'
Requires-Dist: scipy<2.0.0,>=1.11.0; extra == 'descriptive'
Provides-Extra: dicom-seg
Requires-Dist: highdicom<0.23,>=0.22; extra == 'dicom-seg'
Provides-Extra: excel
Requires-Dist: openpyxl<4.0.0,>=3.1.0; extra == 'excel'
Provides-Extra: explainability
Requires-Dist: numpy<2.0.0,>=1.26.0; extra == 'explainability'
Requires-Dist: scikit-learn<2.0.0,>=1.4.0; extra == 'explainability'
Requires-Dist: shap<1.0.0,>=0.45.0; extra == 'explainability'
Provides-Extra: feature-selection
Requires-Dist: boruta<0.4.0,>=0.3.0; extra == 'feature-selection'
Requires-Dist: numpy<2.0.0,>=1.26.0; extra == 'feature-selection'
Requires-Dist: scikit-learn<2.0.0,>=1.4.0; extra == 'feature-selection'
Requires-Dist: scipy<2.0.0,>=1.11.0; extra == 'feature-selection'
Provides-Extra: ml
Requires-Dist: joblib<2.0.0,>=1.3.0; extra == 'ml'
Requires-Dist: matplotlib<4.0.0,>=3.8.0; extra == 'ml'
Requires-Dist: numpy<2.0.0,>=1.26.0; extra == 'ml'
Requires-Dist: scikit-learn<2.0.0,>=1.4.0; extra == 'ml'
Requires-Dist: xgboost<3.0.0,>=2.0.0; extra == 'ml'
Provides-Extra: radiomics
Requires-Dist: pyradiomics<3.1.0,>=3.0.1; extra == 'radiomics'
Provides-Extra: reporting
Provides-Extra: s3
Requires-Dist: boto3<2.0.0,>=1.34.0; extra == 's3'
Provides-Extra: statistics
Requires-Dist: numpy<2.0.0,>=1.26.0; extra == 'statistics'
Requires-Dist: scipy<2.0.0,>=1.11.0; extra == 'statistics'
Provides-Extra: survival
Requires-Dist: lifelines<1.0.0,>=0.30.0; extra == 'survival'
Requires-Dist: matplotlib<4.0.0,>=3.8.0; extra == 'survival'
Requires-Dist: scipy<2.0.0,>=1.11.0; extra == 'survival'
Provides-Extra: survival-ml
Requires-Dist: lifelines<1.0.0,>=0.30.0; extra == 'survival-ml'
Requires-Dist: matplotlib<4.0.0,>=3.8.0; extra == 'survival-ml'
Requires-Dist: scikit-survival<1.0.0,>=0.23.0; extra == 'survival-ml'
Requires-Dist: scipy<2.0.0,>=1.11.0; extra == 'survival-ml'
Provides-Extra: validation
Requires-Dist: numpy<2.0.0,>=1.26.0; extra == 'validation'
Requires-Dist: scikit-learn<2.0.0,>=1.4.0; extra == 'validation'
Provides-Extra: visualization
Requires-Dist: opencv-python-headless<5.0.0,>=4.8.0; extra == 'visualization'
Description-Content-Type: text/markdown

![Fyron Banner](images/BF-Fyron.png)

<div align="center">
  <img alt="Python" src="https://img.shields.io/badge/python-3.10%2B-0B0B0C" />
  <img alt="License" src="https://img.shields.io/badge/license-MIT-0B0B0C" />
  <img alt="FHIR" src="https://img.shields.io/badge/FHIR-enabled-FF6A1A" />
  <img alt="DICOM" src="https://img.shields.io/badge/DICOM-supported-FF6A1A" />
  <img alt="Survival ML" src="https://img.shields.io/badge/survival%20ML-supported-FF6A1A" />
  <a href="https://bitsandflames.github.io/fyron/"><img alt="Docs" src="https://img.shields.io/badge/docs-GitHub%20Pages-0B0B0C" /></a>
</div>

# Fyron

Fyron is a pragmatic Python toolkit for interoperable healthcare data and AI workflows. It provides clean, testable primitives for FHIR, DICOM, imaging, documents, cohort construction, survival analysis, tabular machine learning, LLM-assisted analysis, and BOA visualization.

Full documentation lives at [bitsandflames.github.io/fyron](https://bitsandflames.github.io/fyron/).

## Install

```bash
uv add fyron
```

Useful extras:

| Extra | Install | Adds |
| --- | --- | --- |
| Excel | `uv add "fyron[excel]"` | Excel read/write via `openpyxl` |
| Survival | `uv add "fyron[survival]"` | KM, RMST, Cox, Weibull AFT |
| Survival ML | `uv add "fyron[survival-ml]"` | Gradient survival boosting via `scikit-survival` |
| ML | `uv add "fyron[ml]"` | Random Forest, XGBoost, metrics, plots |
| Boruta | `uv add "fyron[ml,boruta]"` | Boruta feature selection |
| Visualization | `uv add "fyron[visualization]"` | BOA segmentation collages |

For a broad local analysis environment:

```bash
uv add "fyron[survival,survival-ml,ml,visualization,excel]"
```

## Quick Examples

### Console Easter Egg

Fyron keeps normal imports and CLI jobs quiet. The banner is opt-in:

```bash
fyron spark
fyron banner --theme mono --no-version
```

### FHIR Query

```python
from fyron import FHIRRestClient

client = FHIRRestClient("https://hapi.fhir.org/baseR4")
patients = client.search_df("Patient", params={"_count": 10}, max_pages=1)
patients.head()
```

### Cohort Table

```python
from fyron.cohort import build_survival_columns, validate_cohort_table

cohort = build_survival_columns(
    cohort,
    start_col="diagnosis_date",
    end_col="last_followup_or_event_date",
    event_col="event",
)
validate_cohort_table(cohort, required_columns=["patient_id", "time", "event"])
```

### Survival Analysis

```python
from fyron.survival import plot_kaplan_meier, fit_multivariate_cox

plot_kaplan_meier(
    cohort,
    duration_col="time",
    event_col="event",
    group_col="treatment_group",
    at_risk_counts=True,
)

cox = fit_multivariate_cox(
    cohort,
    duration_col="time",
    event_col="event",
    covariates=["age", "stage", "risk_score"],
)
```

### Tabular ML

```python
from fyron import ml

result = ml.run_classification_pipeline(
    X,
    y,
    model="random_forest",
    n_estimators=300,
    random_state=42,
    plot=True,
)

result["metrics"]
```

### Clinical Plots

```python
from fyron import ml

fig_corr, _, corr = ml.plot_correlation_heatmap(X, method="spearman")
fig_metrics, _ = ml.plot_metric_bars({"Random Forest": result["metrics"]})
```

### BOA Visualization

```python
from fyron.visualization import create_boa_segmentation_collage

create_boa_segmentation_collage(
    ["/data/patient_a", "/data/patient_b"],
    "boa_collage.png",
    orientation="axial",
    segmentation_layers=["body_regions", "tissues", "total"],
    slice_fraction=0.5,
)
```

## Modules

| Module | Purpose |
| --- | --- |
| `fyron.fhir` | FHIR REST, SQL, authentication, and resource utilities |
| `fyron.dicom` | DICOMweb download workflows |
| `fyron.imaging` | DICOM/NIfTI I/O and CT/MR normalization |
| `fyron.documents` | Authenticated document downloads |
| `fyron.llm` | LLM-assisted prompts over DataFrames and documents |
| `fyron.core` | Environment loading, local/S3 table I/O, JSON sidecars, Teable cohorts |
| `fyron.cohort` | Patient-level joins, validation, and survival columns |
| `fyron.survival` | KM, RMST, Cox, Weibull AFT, survival boosting |
| `fyron.ml` | Classification models, metrics, plots, feature selection |
| `fyron.boa_extraction` | BOA cohort feature extraction from measurement JSON and NIfTI masks |
| `fyron.visualization` | BOA segmentation collages |

See the [module documentation](https://bitsandflames.github.io/fyron/modules/) for examples for every module.

## Development

```bash
uv sync --all-extras --dev
uv run pytest
```

Preview documentation locally:

```bash
uv run python scripts/build_docs.py
uv run python -m http.server 8001 --directory site
```

GitHub Pages is built from the Markdown files in `docs/` through the BF-native generator in `scripts/build_docs.py`. The Pages workflow publishes the generated `site/` folder when changes land on `main`.

## License

MIT. See [LICENSE](LICENSE).
