diff --git a/README.md b/README.md index 324a5a7..03023c8 100644 --- a/README.md +++ b/README.md @@ -28,21 +28,69 @@ from stroke_segmentor.inferer import Inferer inferer = Inferer() pred = inferer.infer( - dwi_path="path/to/dwi.nii.gz", adc_path="path/to/adc.nii.gz", + dwi_path="path/to/dwi.nii.gz", segmentation_path="seg.nii.gz", # optional. the numpy array is always returned for direct usage ) ``` +## Logging +By default our package is silent, although we do use logging under the hood. +If you want, you can enable it like this: +```py +from loguru import logger + +logger.enable("stroke_segmentor") +``` + + ## Citation > [!IMPORTANT] -> `stroke_segmentor` is part of the [BrainLesion](https://github.com/BrainLesion) suite. -> Please cite it support the development! -> https://github.com/BrainLesion#-citing-brainlesion-suite +> `stroke_segmentor` is based on [DeepISLES](https://github.com/ezequieldlrosa/DeepIsles) and offers its NVAUTO algorithm +> as part of the [BrainLesion](https://github.com/BrainLesion) suite. +> Please cite all relevant manuscripts! + + +### DeepISLES +> de la Rosa, Ezequiel, et al. "DeepISLES: a clinically validated ischemic stroke segmentation model from the ISLES'22 challenge." Nature Communications 16.1 (2025): 7357. +``` + +@article{de2025deepisles, + title={DeepISLES: a clinically validated ischemic stroke segmentation model from the ISLES'22 challenge}, + author={de la Rosa, Ezequiel and Reyes, Mauricio and Liew, Sook-Lei and Hutton, Alexandre and Wiest, Roland and Kaesmacher, Johannes and Hanning, Uta and Hakim, Arsany and Zubal, Richard and Valenzuela, Waldo and others}, + journal={Nature Communications}, + volume={16}, + number={1}, + pages={7357}, + year={2025}, + publisher={Nature Publishing Group UK London} +} +``` + +### BrainLesion Suite +> Kofler, F., Rosier, M., Astaraki, M., Möller, H., Mekki, I. I., Buchner, J. A., ... & Menze, B. (2025). BrainLesion Suite: A Flexible and User-Friendly Framework for Modular Brain Lesion Image Analysis. arXiv preprint arXiv:2507.09036. +``` + +@article{kofler2025brainlesion, + title={BrainLesion Suite: A Flexible and User-Friendly Framework for Modular Brain Lesion Image Analysis}, + author={Kofler, Florian and Rosier, Marcel and Astaraki, Mehdi and M{\"o}ller, Hendrik and Mekki, Ilhem Isra and Buchner, Josef A and Schmick, Anton and Pfiffer, Arianna and Oswald, Eva and Zimmer, Lucas and others}, + journal={arXiv preprint arXiv:2507.09036}, + year={2025} +} +``` + +### NVAUTO Algorithm +>Siddique, M. M. R., Yang, D., He, Y., Xu, D., & Myronenko, A. (2022). Automated ischemic stroke lesion segmentation from 3D MRI. arXiv preprint arXiv:2209.09546. +``` +@article{siddique2022automated, + title={Automated ischemic stroke lesion segmentation from 3D MRI}, + author={Siddique, Md Mahfuzur Rahman and Yang, Dong and He, Yufan and Xu, Daguang and Myronenko, Andriy}, + journal={arXiv preprint arXiv:2209.09546}, + year={2022} +} +``` - This project is based on [DeepISLES](https://github.com/ezequieldlrosa/DeepIsles) and offers its NVAUTO algorithm. - Please cite the [original manuscript](https://github.com/ezequieldlrosa/DeepIsles?tab=readme-ov-file#citations). ## Contributing diff --git a/stroke_segmentor/inferer.py b/stroke_segmentor/inferer.py index 7dbc9fc..e04b5c7 100644 --- a/stroke_segmentor/inferer.py +++ b/stroke_segmentor/inferer.py @@ -8,6 +8,7 @@ from numpy.typing import NDArray from stroke_segmentor.model_handler import ModelHandler +from stroke_segmentor.utils.citation_reminder import citation_reminder class Inferer: @@ -57,6 +58,7 @@ def _save( Path(segmentation_path).parent.mkdir(parents=True, exist_ok=True) SimpleITK.WriteImage(output_image, str(segmentation_path)) + @citation_reminder def infer( self, adc_path: Union[str, Path], diff --git a/stroke_segmentor/utils/__init__.py b/stroke_segmentor/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/stroke_segmentor/utils/citation_reminder.py b/stroke_segmentor/utils/citation_reminder.py new file mode 100644 index 0000000..5e397c3 --- /dev/null +++ b/stroke_segmentor/utils/citation_reminder.py @@ -0,0 +1,57 @@ +import os + +from rich.console import Console + + +CITATION_OVERVIEW_URL = ( + "https://github.com/BrainLesion/stroke_segmentor?tab=readme-ov-file#citation" +) +DEEP_ISLES_PAPER_URL = "https://pubmed.ncbi.nlm.nih.gov/40783484/" +DEEP_ISLES_PAPER_TEXT = 'de la Rosa, Ezequiel, et al. "DeepISLES: a clinically validated ischemic stroke segmentation model from the ISLES\'22 challenge." Nature Communications 16.1 (2025): 7357.' + +NVAUTO_PAPER_URL = "https://arxiv.org/abs/2209.09546" +NVAUTO_PAPER_TEST = "Siddique, M. M. R., Yang, D., He, Y., Xu, D., & Myronenko, A. (2022). Automated ischemic stroke lesion segmentation from 3D MRI. arXiv preprint arXiv:2209.09546." + +BRAINLES_PAPER_URL = "https://arxiv.org/abs/2507.09036" +BRAINLES_PAPER_TEXT = "Kofler, F., Rosier, M., Astaraki, M., Möller, H., Mekki, I. I., Buchner, J. A., ... & Menze, B. (2025). BrainLesion Suite: A Flexible and User-Friendly Framework for Modular Brain Lesion Image Analysis. arXiv preprint arXiv:2507.09036." + + +def citation_reminder(func): + """Decorator to remind users to cite stroke-segmentor.""" + + def wrapper(*args, **kwargs): + if ( + os.environ.get("STROKE_SEGMENTOR_CITATION_REMINDER", "true").lower() + == "true" + ): + console = Console() + console.rule("Thank you for using [bold]stroke-segmentor[/bold]") + console.print( + "This is the NVAUTO algorithmic solution from the ISLES'22 challenge.", + justify="center", + ) + console.print( + "If you are using this tool, please cite the following work:", + justify="center", + ) + console.print( + f"[italic]{DEEP_ISLES_PAPER_TEXT}[/italic] ({DEEP_ISLES_PAPER_URL})", + justify="center", + ) + console.print( + f"[italic]{BRAINLES_PAPER_TEXT}[/italic] ({BRAINLES_PAPER_URL})", + justify="center", + ) + console.print( + f"[italic]{NVAUTO_PAPER_TEST}[/italic] ({NVAUTO_PAPER_URL})", + justify="center", + ) + console.print( + f"This information along with bibtex entries can be found at {CITATION_OVERVIEW_URL}", + justify="center", + ) + console.rule() + console.line() + return func(*args, **kwargs) + + return wrapper diff --git a/stroke_segmentor/zenodo.py b/stroke_segmentor/zenodo.py index ec7397f..f8f94e9 100644 --- a/stroke_segmentor/zenodo.py +++ b/stroke_segmentor/zenodo.py @@ -176,6 +176,7 @@ def _extract_archive( with zipfile.ZipFile(buffer) as z: z.extractall(folder) + logger.info(f"Extracted data to {folder}") for file in folder.iterdir(): if file.is_file() and file.suffix == ".zip":