diff --git a/.gitattributes b/.gitattributes index 1d50726..a6344aa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,4 +33,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text -nnunet_results/Dataset903_Task903_DLMUSEV2/nnUNetTrainer__nnUNetPlans__3d_fullres/crossval_results_folds_0/summary.json filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..b61bf9e --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,40 @@ +name: Upload Python Package + +on: workflow_dispatch + +permissions: + contents: read + id-token: write # Allow GitHub to mint tokens + +jobs: + pypi-publish: + name: Upload release to PyPI + runs-on: ubuntu-latest # Can use macos-latest if needed + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: "3.x" + + - name: Install dependencies + run: | + pip install setuptools + pip install twine + pip install wheel + sudo apt-get install jq + + - name: Clean previous builds + run: rm -rf dist + + - name: Build package + run: python setup.py sdist bdist_wheel + + - name: Publish package to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: twine upload --repository-url https://upload.pypi.org/legacy/ dist/* diff --git a/README.md b/README.md index bd1ffd6..e64e23a 100644 --- a/README.md +++ b/README.md @@ -20,40 +20,13 @@ cd DLMUSE pip install -e . ``` -### Using docker(OUTDATED) - -```bash -docker pull aidinisg/dlmuse:0.0.1 -``` - ## Usage -A pre-trained nnUNet model can be found in the [DLMUSEV2-1.0.0 release](https://github.com/CBICA/DLMUSE/releases/tag/v1.0.0). Feel free to use it under the package's [license](LICENSE). +A pre-trained nnUNet model can be found at our [hugging face account](https://huggingface.co/nichart/DLMUSE/tree/main) or at the [DLMUSEV2-1.0.0 release](https://github.com/CBICA/DLMUSE/releases/tag/v1.0.0). Feel free to use it under the package's [license](LICENSE). ### From command line ```bash -DLMUSE -i "image_folder" -o "path to output folder" -m "path to model weights" -f 0 -tr nnUNetTrainer -c 3d_fullres -p nnUNetPlans -d "id" -device cuda/cpu/mps -``` - -### Using the docker container(OUTDATED) - -In the [docker container](https://hub.docker.com/repository/docker/aidinisg/dlmuse/general), the default model is included, but you can also provide your own. - -Without providing a model: - -```bash -docker run --gpus all -it --rm -v /path/to/local/input:/workspace/input \ - -v /path/to/local/output:/workspace/output \ - aidinisg/dlmuse:0.0.1 -i input/ -o output/ -``` - -Providing a model: - -```bash -docker run --gpus all -it --rm -v /path/to/local/model:/workspace/model \ - -v /path/to/local/input:/workspace/input \ - -v /path/to/local/output:/workspace/output \ - aidinisg/dlmuse:0.0.1 -i input/ -o output/ --model model/ +DLMUSE -i "image_folder" -o "path to output folder" -device cuda/mps/cpu ``` ## Contact diff --git a/nnunet_output/dataset.json b/nnunet_output/dataset.json new file mode 100644 index 0000000..c39f8d0 --- /dev/null +++ b/nnunet_output/dataset.json @@ -0,0 +1,11 @@ +{ + "channel_names": { + "0": "MRI" + }, + "file_ending": ".nii.gz", + "labels": { + "background": 0, + "class1": 1 + }, + "numTraining": 1806 +} \ No newline at end of file diff --git a/nnunet_output/plans.json b/nnunet_output/plans.json new file mode 100644 index 0000000..0849bf1 --- /dev/null +++ b/nnunet_output/plans.json @@ -0,0 +1,434 @@ +{ + "dataset_name": "Dataset901_Task901_dlicv", + "plans_name": "nnUNetPlans", + "original_median_spacing_after_transp": [ + 1.0, + 1.0, + 1.0 + ], + "original_median_shape_after_transp": [ + 255, + 255, + 176 + ], + "image_reader_writer": "SimpleITKIO", + "transpose_forward": [ + 0, + 1, + 2 + ], + "transpose_backward": [ + 0, + 1, + 2 + ], + "configurations": { + "2d": { + "data_identifier": "nnUNetPlans_2d", + "preprocessor_name": "DefaultPreprocessor", + "batch_size": 66, + "patch_size": [ + 256, + 192 + ], + "median_image_size_in_voxels": [ + 240.0, + 179.0 + ], + "spacing": [ + 1.0, + 1.0 + ], + "normalization_schemes": [ + "ZScoreNormalization" + ], + "use_mask_for_norm": [ + false + ], + "UNet_class_name": "PlainConvUNet", + "UNet_base_num_features": 32, + "n_conv_per_stage_encoder": [ + 2, + 2, + 2, + 2, + 2, + 2 + ], + "n_conv_per_stage_decoder": [ + 2, + 2, + 2, + 2, + 2 + ], + "num_pool_per_axis": [ + 5, + 5 + ], + "pool_op_kernel_sizes": [ + [ + 1, + 1 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ] + ], + "conv_kernel_sizes": [ + [ + 3, + 3 + ], + [ + 3, + 3 + ], + [ + 3, + 3 + ], + [ + 3, + 3 + ], + [ + 3, + 3 + ], + [ + 3, + 3 + ] + ], + "unet_max_num_features": 512, + "resampling_fn_data": "resample_data_or_seg_to_shape", + "resampling_fn_seg": "resample_data_or_seg_to_shape", + "resampling_fn_data_kwargs": { + "is_seg": false, + "order": 3, + "order_z": 0, + "force_separate_z": null + }, + "resampling_fn_seg_kwargs": { + "is_seg": true, + "order": 1, + "order_z": 0, + "force_separate_z": null + }, + "resampling_fn_probabilities": "resample_data_or_seg_to_shape", + "resampling_fn_probabilities_kwargs": { + "is_seg": false, + "order": 1, + "order_z": 0, + "force_separate_z": null + }, + "batch_dice": true + }, + "3d_lowres": { + "data_identifier": "nnUNetPlans_3d_lowres", + "preprocessor_name": "DefaultPreprocessor", + "batch_size": 2, + "patch_size": [ + 160, + 128, + 112 + ], + "median_image_size_in_voxels": [ + 235, + 226, + 169 + ], + "spacing": [ + 1.0609, + 1.0609, + 1.0609 + ], + "normalization_schemes": [ + "ZScoreNormalization" + ], + "use_mask_for_norm": [ + false + ], + "UNet_class_name": "PlainConvUNet", + "UNet_base_num_features": 32, + "n_conv_per_stage_encoder": [ + 2, + 2, + 2, + 2, + 2, + 2 + ], + "n_conv_per_stage_decoder": [ + 2, + 2, + 2, + 2, + 2 + ], + "num_pool_per_axis": [ + 5, + 5, + 4 + ], + "pool_op_kernel_sizes": [ + [ + 1, + 1, + 1 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 1 + ] + ], + "conv_kernel_sizes": [ + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ] + ], + "unet_max_num_features": 320, + "resampling_fn_data": "resample_data_or_seg_to_shape", + "resampling_fn_seg": "resample_data_or_seg_to_shape", + "resampling_fn_data_kwargs": { + "is_seg": false, + "order": 3, + "order_z": 0, + "force_separate_z": null + }, + "resampling_fn_seg_kwargs": { + "is_seg": true, + "order": 1, + "order_z": 0, + "force_separate_z": null + }, + "resampling_fn_probabilities": "resample_data_or_seg_to_shape", + "resampling_fn_probabilities_kwargs": { + "is_seg": false, + "order": 1, + "order_z": 0, + "force_separate_z": null + }, + "batch_dice": false, + "next_stage": "3d_cascade_fullres" + }, + "3d_fullres": { + "data_identifier": "nnUNetPlans_3d_fullres", + "preprocessor_name": "DefaultPreprocessor", + "batch_size": 2, + "patch_size": [ + 160, + 128, + 112 + ], + "median_image_size_in_voxels": [ + 249.0, + 240.0, + 179.0 + ], + "spacing": [ + 1.0, + 1.0, + 1.0 + ], + "normalization_schemes": [ + "ZScoreNormalization" + ], + "use_mask_for_norm": [ + false + ], + "UNet_class_name": "PlainConvUNet", + "UNet_base_num_features": 32, + "n_conv_per_stage_encoder": [ + 2, + 2, + 2, + 2, + 2, + 2 + ], + "n_conv_per_stage_decoder": [ + 2, + 2, + 2, + 2, + 2 + ], + "num_pool_per_axis": [ + 5, + 5, + 4 + ], + "pool_op_kernel_sizes": [ + [ + 1, + 1, + 1 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 2 + ], + [ + 2, + 2, + 1 + ] + ], + "conv_kernel_sizes": [ + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ], + [ + 3, + 3, + 3 + ] + ], + "unet_max_num_features": 320, + "resampling_fn_data": "resample_data_or_seg_to_shape", + "resampling_fn_seg": "resample_data_or_seg_to_shape", + "resampling_fn_data_kwargs": { + "is_seg": false, + "order": 3, + "order_z": 0, + "force_separate_z": null + }, + "resampling_fn_seg_kwargs": { + "is_seg": true, + "order": 1, + "order_z": 0, + "force_separate_z": null + }, + "resampling_fn_probabilities": "resample_data_or_seg_to_shape", + "resampling_fn_probabilities_kwargs": { + "is_seg": false, + "order": 1, + "order_z": 0, + "force_separate_z": null + }, + "batch_dice": true + }, + "3d_cascade_fullres": { + "inherits_from": "3d_fullres", + "previous_stage": "3d_lowres" + } + }, + "experiment_planner_used": "ExperimentPlanner", + "label_manager": "LabelManager", + "foreground_intensity_properties_per_channel": { + "0": { + "max": 8952.697265625, + "mean": 528.2257080078125, + "median": 317.0, + "min": -24.0, + "percentile_00_5": 20.0, + "percentile_99_5": 3972.0, + "std": 636.9642333984375 + } + } +} \ No newline at end of file diff --git a/nnunet_output/predict_from_raw_data_args.json b/nnunet_output/predict_from_raw_data_args.json new file mode 100644 index 0000000..7f7ed21 --- /dev/null +++ b/nnunet_output/predict_from_raw_data_args.json @@ -0,0 +1,11 @@ +{ + "folder_with_segs_from_prev_stage": null, + "list_of_lists_or_source_folder": "nnunet_output/renamed_image", + "num_parts": 1, + "num_processes_preprocessing": 3, + "num_processes_segmentation_export": 3, + "output_folder_or_list_of_truncated_output_files": "nnunet_output/", + "overwrite": true, + "part_id": 0, + "save_probabilities": false +} \ No newline at end of file diff --git a/nnunet_output/renamed_image/renaming.json b/nnunet_output/renamed_image/renaming.json new file mode 100644 index 0000000..bbb9214 --- /dev/null +++ b/nnunet_output/renamed_image/renaming.json @@ -0,0 +1,6 @@ +{ + "test4_t1.nii.gz": "case_ 000_0000.nii.gz", + "test2_t1.nii.gz": "case_ 001_0000.nii.gz", + "test3_t1.nii.gz": "case_ 002_0000.nii.gz", + "test1_t1.nii.gz": "case_ 003_0000.nii.gz" +} \ No newline at end of file diff --git a/src/__main__.py b/src/__main__.py index ccf083f..f46174e 100644 --- a/src/__main__.py +++ b/src/__main__.py @@ -1,8 +1,8 @@ import argparse import json import os -import sys import shutil +import sys import warnings import torch @@ -188,25 +188,17 @@ def main() -> None: ) args = parser.parse_args() - #args.f = [i if i == "all" else int(i) for i in args.f] args.f = [args.f] # data conversion src_folder = args.i # input folder - #des_folder = args.o + + # des_folder = args.o if not os.path.exists(args.o): # create output folder if it does not exist os.makedirs(args.o) des_folder = os.path.join(args.o, "renamed_image") - # prepare_data_folder(des_folder) - # rename_dic, rename_back_dict = rename_and_copy_files(src_folder, des_folder) - - # datalist_file = os.path.join(des_folder, "renaming.json") - # with open(datalist_file, "w", encoding="utf-8") as f: - # json.dump(rename_dic, f, ensure_ascii=False, indent=4) - # print(f"Renaming dic is saved to {datalist_file}") - # check if -i argument is a folder, list (csv), or a single file (nii.gz) if os.path.isdir(args.i): # if args.i is a directory src_folder = args.i @@ -266,7 +258,6 @@ def main() -> None: device = torch.device("mps") print("Running in MPS mode.") - # exports for nnunetv2 purposes os.environ["nnUNet_raw"] = "/nnunet_raw/" os.environ["nnUNet_preprocessed"] = "/nnunet_preprocessed"