From 58c3f13d63572df8e4239959be4b8a5cf981ad50 Mon Sep 17 00:00:00 2001 From: Marcel Rosier Date: Wed, 3 Sep 2025 18:17:58 +0200 Subject: [PATCH 1/7] Fix param order --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 324a5a7..e275400 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ 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 ) ``` From 4f9212a79130cb07ed25fb013f9d343685a7e788 Mon Sep 17 00:00:00 2001 From: Marcel Rosier Date: Wed, 3 Sep 2025 18:37:45 +0200 Subject: [PATCH 2/7] Add citation reminder --- stroke_segmentor/inferer.py | 2 + stroke_segmentor/utils/__init__.py | 0 stroke_segmentor/utils/citation_reminder.py | 50 +++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 stroke_segmentor/utils/__init__.py create mode 100644 stroke_segmentor/utils/citation_reminder.py 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..1887f22 --- /dev/null +++ b/stroke_segmentor/utils/citation_reminder.py @@ -0,0 +1,50 @@ +import os + +from rich.console import Console + +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, Md Mahfuzur Rahman, et al. "Automated ischemic stroke lesion segmentation from 3D MRI." arXiv preprint arXiv:2209.09546 (2022).' + +BRAINLES_PAPER_URL = "https://arxiv.org/abs/2507.09036" +BRAINLES_PAPER_TEXT = 'Kofler, Florian, et al. "BrainLesion Suite: A Flexible and User-Friendly Framework for Modular Brain Lesion Image Analysis." arXiv preprint arXiv:2507.09036 (2025).' + + +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]{NVAUTO_PAPER_TEST}[/italic] ({NVAUTO_PAPER_URL})", + 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.rule() + console.line() + os.environ["PANOPTICA_CITATION_REMINDER"] = "false" # Show only once + return func(*args, **kwargs) + + return wrapper From 260e5da8d804d8f0e1b82d096440ec6d03367969 Mon Sep 17 00:00:00 2001 From: Marcel Rosier Date: Wed, 3 Sep 2025 18:52:18 +0200 Subject: [PATCH 3/7] Update and extend citations --- README.md | 48 ++++++++++++++++++--- stroke_segmentor/utils/citation_reminder.py | 18 +++++--- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e275400..d0a0505 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,50 @@ pred = inferer.infer( ## 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 mansucripts! + + +### 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/utils/citation_reminder.py b/stroke_segmentor/utils/citation_reminder.py index 1887f22..e02861d 100644 --- a/stroke_segmentor/utils/citation_reminder.py +++ b/stroke_segmentor/utils/citation_reminder.py @@ -2,14 +2,18 @@ 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, Md Mahfuzur Rahman, et al. "Automated ischemic stroke lesion segmentation from 3D MRI." arXiv preprint arXiv:2209.09546 (2022).' +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, Florian, et al. "BrainLesion Suite: A Flexible and User-Friendly Framework for Modular Brain Lesion Image Analysis." arXiv preprint arXiv:2507.09036 (2025).' +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): @@ -31,15 +35,19 @@ def wrapper(*args, **kwargs): justify="center", ) console.print( - f"[italic]{NVAUTO_PAPER_TEST}[/italic] ({NVAUTO_PAPER_URL})", + f"[italic]{DEEP_ISLES_PAPER_TEXT}[/italic] ({DEEP_ISLES_PAPER_URL})", justify="center", ) console.print( - f"[italic]{DEEP_ISLES_PAPER_TEXT}[/italic] ({DEEP_ISLES_PAPER_URL})", + f"[italic]{BRAINLES_PAPER_TEXT}[/italic] ({BRAINLES_PAPER_URL})", justify="center", ) console.print( - f"[italic]{BRAINLES_PAPER_TEXT}[/italic] ({BRAINLES_PAPER_URL})", + 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() From a840bd1629a6c439536769d7d090c1deed8d1f3f Mon Sep 17 00:00:00 2001 From: Marcel Rosier Date: Wed, 3 Sep 2025 19:07:32 +0200 Subject: [PATCH 4/7] Add info for logging --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0a0505..03023c8 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,22 @@ pred = inferer.infer( ) ``` +## 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 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 mansucripts! +> Please cite all relevant manuscripts! ### DeepISLES From 307d4500fab89f23a56aabad8294bb6b70383aef Mon Sep 17 00:00:00 2001 From: Marcel Rosier Date: Wed, 3 Sep 2025 19:07:48 +0200 Subject: [PATCH 5/7] Log weights location --- stroke_segmentor/zenodo.py | 1 + 1 file changed, 1 insertion(+) 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": From cb244b3bd660bb6f44e1798ef664f260c73b0968 Mon Sep 17 00:00:00 2001 From: marcel rosier <32431395+MarcelRosier@users.noreply.github.com> Date: Wed, 3 Sep 2025 19:11:24 +0200 Subject: [PATCH 6/7] Update stroke_segmentor/utils/citation_reminder.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- stroke_segmentor/utils/citation_reminder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stroke_segmentor/utils/citation_reminder.py b/stroke_segmentor/utils/citation_reminder.py index e02861d..4b77f91 100644 --- a/stroke_segmentor/utils/citation_reminder.py +++ b/stroke_segmentor/utils/citation_reminder.py @@ -52,7 +52,7 @@ def wrapper(*args, **kwargs): ) console.rule() console.line() - os.environ["PANOPTICA_CITATION_REMINDER"] = "false" # Show only once + os.environ["STROKE_SEGMENTOR_CITATION_REMINDER"] = "false" # Show only once return func(*args, **kwargs) return wrapper From b0bd91452b50ff65ee6f50bffeeae6e61b5a75e6 Mon Sep 17 00:00:00 2001 From: Marcel Rosier Date: Wed, 3 Sep 2025 19:12:06 +0200 Subject: [PATCH 7/7] Always show reminder --- stroke_segmentor/utils/citation_reminder.py | 1 - 1 file changed, 1 deletion(-) diff --git a/stroke_segmentor/utils/citation_reminder.py b/stroke_segmentor/utils/citation_reminder.py index 4b77f91..5e397c3 100644 --- a/stroke_segmentor/utils/citation_reminder.py +++ b/stroke_segmentor/utils/citation_reminder.py @@ -52,7 +52,6 @@ def wrapper(*args, **kwargs): ) console.rule() console.line() - os.environ["STROKE_SEGMENTOR_CITATION_REMINDER"] = "false" # Show only once return func(*args, **kwargs) return wrapper