Metadata-Version: 2.1
Name: autorad
Version: 0.1.2
Summary: Radiomics-related modules for extraction and experimenting
Home-page: https://github.com/pwoznicki/AutoRadiomics
Author: Piotr Woznicki
Author-email: piotrekwoznicki@gmail.com
License: Apache 2.0
Project-URL: Bug Tracker, https://github.com/pwoznicki/AutoRadiomics
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: scikit-image (==0.19.2)
Requires-Dist: patsy (==0.5.2)
Requires-Dist: statsmodels (==0.13.2)
Requires-Dist: alembic (==1.7.5)
Requires-Dist: attrs (==21.4.0)
Requires-Dist: autopage (==0.5.0)
Requires-Dist: Boruta (==0.3)
Requires-Dist: certifi (==2021.10.8)
Requires-Dist: charset-normalizer (==2.0.10)
Requires-Dist: click
Requires-Dist: cliff (==3.10.0)
Requires-Dist: cloudpickle (==2.0.0)
Requires-Dist: cmaes (==0.8.2)
Requires-Dist: cmd2 (==2.3.3)
Requires-Dist: colorlog (==6.6.0)
Requires-Dist: cycler (==0.11.0)
Requires-Dist: databricks-cli (==0.16.2)
Requires-Dist: docopt (==0.6.2)
Requires-Dist: entrypoints (==0.3)
Requires-Dist: Flask (==2.0.2)
Requires-Dist: fonttools (==4.29.0)
Requires-Dist: gitdb (==4.0.9)
Requires-Dist: GitPython
Requires-Dist: greenlet (==1.1.2)
Requires-Dist: gunicorn (==20.1.0)
Requires-Dist: idna (==3.3)
Requires-Dist: imbalanced-learn (==0.9.0)
Requires-Dist: importlib-metadata (==4.10.1)
Requires-Dist: importlib-resources (==5.4.0)
Requires-Dist: itsdangerous (==2.0.1)
Requires-Dist: Jinja2 (==3.0.3)
Requires-Dist: joblib (==1.1.0)
Requires-Dist: kiwisolver (==1.3.2)
Requires-Dist: lightgbm (==3.3.2)
Requires-Dist: lofo-importance (==0.3.1)
Requires-Dist: Mako (==1.1.6)
Requires-Dist: MarkupSafe (==2.0.1)
Requires-Dist: matplotlib (==3.5.1)
Requires-Dist: MedPy (==0.4.0)
Requires-Dist: mlflow (==1.23.0)
Requires-Dist: monai (==0.8.0)
Requires-Dist: nibabel (==3.2.1)
Requires-Dist: nilearn (==0.9.0)
Requires-Dist: numpy (==1.22.1)
Requires-Dist: optuna (==2.10.0)
Requires-Dist: packaging (==21.3)
Requires-Dist: pandas (==1.4.0)
Requires-Dist: pbr (==5.8.0)
Requires-Dist: Pillow (==9.0.0)
Requires-Dist: plotly (==5.5.0)
Requires-Dist: prettytable (==3.0.0)
Requires-Dist: prometheus-client (==0.12.0)
Requires-Dist: prometheus-flask-exporter (==0.18.7)
Requires-Dist: protobuf (==3.19.3)
Requires-Dist: pykwalify (==1.8.0)
Requires-Dist: pyparsing (==2.4.7)
Requires-Dist: pyperclip (==1.8.2)
Requires-Dist: pyradiomics (==3.0.1)
Requires-Dist: python-dateutil (==2.8.2)
Requires-Dist: pytz (==2021.3)
Requires-Dist: PyWavelets (==1.2.0)
Requires-Dist: PyYAML (==6.0)
Requires-Dist: querystring-parser (==1.2.4)
Requires-Dist: requests (==2.27.1)
Requires-Dist: ruamel.yaml (==0.17.17)
Requires-Dist: ruamel.yaml.clib (==0.2.6)
Requires-Dist: scikit-learn (==1.0.2)
Requires-Dist: scipy (==1.7.3)
Requires-Dist: seaborn (==0.11.2)
Requires-Dist: SimpleITK (==2.1.1.1)
Requires-Dist: six (==1.16.0)
Requires-Dist: smmap (==5.0.0)
Requires-Dist: SQLAlchemy (==1.4.31)
Requires-Dist: sqlparse (==0.4.2)
Requires-Dist: stevedore (==3.5.0)
Requires-Dist: tabulate (==0.8.9)
Requires-Dist: tenacity (==8.0.1)
Requires-Dist: testresources (==2.0.1)
Requires-Dist: threadpoolctl (==3.0.0)
Requires-Dist: torch (==1.11.0)
Requires-Dist: tqdm (==4.62.3)
Requires-Dist: typer (==0.4.0)
Requires-Dist: typing-extensions (==4.0.1)
Requires-Dist: urllib3 (==1.26.8)
Requires-Dist: wcwidth (==0.2.5)
Requires-Dist: websocket-client (==1.2.3)
Requires-Dist: Werkzeug (==2.0.2)
Requires-Dist: xgboost (==1.5.2)
Requires-Dist: zipp (==3.7.0)
Provides-Extra: app
Requires-Dist: streamlit (==1.2.0) ; extra == 'app'
Requires-Dist: docker (==5.0.3) ; extra == 'app'
Requires-Dist: jupytext (==1.13.8) ; extra == 'app'
Provides-Extra: dev
Requires-Dist: coverage (==6.2) ; extra == 'dev'
Requires-Dist: great-expectations (==0.14.2) ; extra == 'dev'
Requires-Dist: pytest (==6.2.5) ; extra == 'dev'
Requires-Dist: hypothesis (==6.36.0) ; extra == 'dev'
Requires-Dist: black (==21.12b0) ; extra == 'dev'
Requires-Dist: flake8 (==4.0.1) ; extra == 'dev'
Requires-Dist: isort (==5.10.1) ; extra == 'dev'
Requires-Dist: pre-commit (==2.17.0) ; extra == 'dev'
Requires-Dist: streamlit (==1.2.0) ; extra == 'dev'
Requires-Dist: docker (==5.0.3) ; extra == 'dev'
Requires-Dist: jupytext (==1.13.8) ; extra == 'dev'
Requires-Dist: mkdocs (==1.1.2) ; extra == 'dev'
Requires-Dist: mkdocs-material (==7.2.3) ; extra == 'dev'
Requires-Dist: mkdocstrings (==0.15.2) ; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs (==1.1.2) ; extra == 'docs'
Requires-Dist: mkdocs-material (==7.2.3) ; extra == 'docs'
Requires-Dist: mkdocstrings (==0.15.2) ; extra == 'docs'

<p align="center">
<br>
  <img src="docs/images/logo.png" alt="AutoRadiomics">
</p>

[![License](https://img.shields.io/badge/license-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)
[![CI Build](https://github.com/pwoznicki/AutoRadiomics/actions/workflows/testing.yml/badge.svg)](https://github.com/pwoznicki/AutoRadiomics/commits/main)
[![codecov](https://codecov.io/gh/pwoznicki/AutoRadiomics/branch/main/graph/badge.svg)](https://codecov.io/gh/pwoznicki/AutoRadiomics)

## Simple pipeline for experimenting with radiomics features

| <p align="center"><a href="https://share.streamlit.io/pwoznicki/autoradiomics/main/webapp/app.py"> Streamlit Share | <p align="center"><a href="https://hub.docker.com/repository/docker/piotrekwoznicki/autorad"> Docker          | <p align="center"><a href="https://pypi.org/project/autorad/"> Python                                          |
| ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| <p align="center"><img src="https://github.com/pwoznicki/AutoRadiomics/raw/main/docs/images/streamlit.png" /></p>  | <p align="center"><img src="https://github.com/pwoznicki/AutoRadiomics/raw/main/docs/images/docker.png"/></p> | <p align="center"><img src="https://github.com/pwoznicki/AutoRadiomics/raw/main/docs/images/python.png" /></p> |
| <p align="center"><a href="https://share.streamlit.io/pwoznicki/autoradiomics/main/webapp/app.py"> **Demo**        | `docker run -p 8501:8501 -v <your_data_dir>:/data -it piotrekwoznicki/autorad:0.2`                            | `pip install --upgrade autorad`                                                                                |

&nbsp;

### Installation from source

```bash
git clone https://github.com/pwoznicki/AutoRadiomics.git
cd AutoRadiomics
pip install -e .
```

## Example - Hydronephrosis detection from CT images:

### Extract radiomics features

```python
df = pd.read_csv(table_dir / "paths.csv")
image_dataset = ImageDataset(
    df=df,
    image_colname="image path",
    mask_colname="mask path",
    ID_colname="patient ID"
)
extractor = FeatureExtractor(
    dataset=image_dataset,
    out_path=(table_dir / "features.csv"),
)
extractor.extract_features()
```

### Load, split and preprocess extracted features

```python
# Create a dataset from the radiomics features
feature_df = pd.read_csv(table_dir / "features.csv")
feature_dataset = FeatureDataset(
    dataframe=feature_df,
    target="Hydronephrosis",
    task_name="Hydronephrosis detection"
)

# Split data and load splits
splits_path = result_dir / "splits.json"
feature_dataset.full_split(save_path=splits_path)
feature_dataset.load_splits_from_json(splits_path)

# Preprocessing
preprocessor = Preprocessor(
    normalize=True,
    feature_selection_method="boruta",
    oversampling_method="SMOTE",
)
feature_dataset._data = preprocessor.fit_transform(dataset.data)
```

### Train the model for hydronephrosis classification

```python
# Select classifiers to compare
classifier_names = [
    "Gaussian Process Classifier",
    "Logistic Regression",
    "SVM",
    "Random Forest",
    "XGBoost",
]
classifiers = [MLClassifier.from_sklearn(name) for name in classifier_names]

model = MLClassifier.from_sklearn(name="Random Forest")
model.set_optimizer("optuna", n_trials=5)

trainer = Trainer(
    dataset=dataset,
    models=[model],
    result_dir=result_dir,
    experiment_name="Hydronephrosis detection"
)
trainer.run()
```

### Create an evaluator to train and evaluate selected classifiers

```python
evaluator = Evaluator(dataset=data, models=classifiers)
evaluator.evaluate_cross_validation()
evaluator.boxplot_by_class()
evaluator.plot_all_cross_validation()
evaluator.plot_test()
```

## Commands

### MLFlow

```bash
mlflow server -h 0.0.0.0 -p 5000 --backend-store-uri <result_dir>
```

## Dependencies:

- MONAI
- pyRadiomics
- MLFlow
- Optuna
- scikit-learn
- imbalanced-learn
- XGBoost
- Boruta
- Medpy
- NiBabel
- nilearn
- plotly
- seaborn

### App dependencies:

- Streamlit
- Docker


