diff --git a/.devcontainer/onCreateCommand.sh b/.devcontainer/onCreateCommand.sh index bd69500a8..fe14726b0 100755 --- a/.devcontainer/onCreateCommand.sh +++ b/.devcontainer/onCreateCommand.sh @@ -5,4 +5,4 @@ pip install wheel pip install openvino-dev==2023.0.1 # [OPTIONAL] to generate optimized models for inference pip install mlcube_docker # [OPTIONAL] to deploy GaNDLF models as MLCube-compliant Docker containers pip install medmnist==2.1.0 -pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cpu +pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cpu diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh index e938ebaa8..fc79af237 100755 --- a/.devcontainer/postCreateCommand.sh +++ b/.devcontainer/postCreateCommand.sh @@ -6,7 +6,7 @@ # if runnning on a GPU machine, install the GPU version of pytorch if command -v nvidia-smi &> /dev/null then - pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116 + pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118 fi pip install -e . diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index 8869fcac7..bf11ee661 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -28,7 +28,7 @@ jobs: # if: steps.changed-files-specific.outputs.only_modified == 'false' - name: Detect and screen file changes id: changed-files-specific - uses: tj-actions/changed-files@v34 + uses: tj-actions/changed-files@v41 with: files: | docs/** diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index e7b67070e..92c5cde27 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -25,8 +25,8 @@ jobs: fail-fast: false # So that remaining jobs don't instantly quit if one fails (e.g, CPU/ROCm don't upload if CUDA just fails to push to ghcr...) matrix: include: # Platform locates Dockerfile ("Dockerfile-{PLATFORM}"), docker tag has to be all lowercase alphanumeric for mysterious docker reasons - - platform: CUDA11.6 - dockertag: cuda116 + - platform: CUDA11.8 + dockertag: cuda118 - platform: CPU dockertag: cpu # - platform: ROCm diff --git a/.github/workflows/mlcube-test.yml b/.github/workflows/mlcube-test.yml index 1c5b3e58c..43716676b 100644 --- a/.github/workflows/mlcube-test.yml +++ b/.github/workflows/mlcube-test.yml @@ -32,7 +32,7 @@ jobs: # if: steps.changed-files-specific.outputs.only_modified == 'false' - name: Detect and screen file changes id: changed-files-specific - uses: tj-actions/changed-files@v34 + uses: tj-actions/changed-files@v41 with: files: | .github/*.md @@ -73,7 +73,7 @@ jobs: python -m pip install --upgrade pip python -m pip install wheel python -m pip install openvino-dev==2023.0.1 mlcube_docker - pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cpu + pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cpu pip install -e . - name: Run mlcube deploy tests working-directory: ./testing diff --git a/.github/workflows/openfl-test.yml b/.github/workflows/openfl-test.yml index 99db48023..dbc9958e0 100644 --- a/.github/workflows/openfl-test.yml +++ b/.github/workflows/openfl-test.yml @@ -33,7 +33,7 @@ jobs: # if: steps.changed-files-specific.outputs.only_modified == 'false' - name: Detect and screen file changes id: changed-files-specific - uses: tj-actions/changed-files@v34 + uses: tj-actions/changed-files@v41 with: files: | .github/*.md @@ -73,7 +73,7 @@ jobs: sudo apt-get install libvips libvips-tools -y python -m pip install --upgrade pip python -m pip install wheel - pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cpu + pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cpu pip install -e . - name: Run generic unit tests to download data and construct CSVs if: steps.changed-files-specific.outputs.only_modified == 'false' # Run on any non-docs change diff --git a/.github/workflows/python-install-check.yml b/.github/workflows/python-install-check.yml new file mode 100644 index 000000000..7ec37528a --- /dev/null +++ b/.github/workflows/python-install-check.yml @@ -0,0 +1,22 @@ +name: Install across python versions + +on: [push, pull_request] + +jobs: + pyversion_install: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11"] + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + # all good if installation finishes + python -m pip install -e . diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index efbabbdd9..783d17c4c 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -33,7 +33,7 @@ jobs: # if: steps.changed-files-specific.outputs.only_modified == 'false' - name: Detect and screen file changes id: changed-files-specific - uses: tj-actions/changed-files@v34 + uses: tj-actions/changed-files@v41 with: files: | .github/*.md @@ -74,7 +74,7 @@ jobs: python -m pip install --upgrade pip python -m pip install wheel python -m pip install openvino-dev==2023.0.1 mlcube_docker - pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cpu + pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cpu pip install -e . - name: Run generic unit tests if: steps.changed-files-specific.outputs.only_modified == 'false' # Run on any non-docs change diff --git a/Dockerfile-CPU b/Dockerfile-CPU index 0120f2af1..d06cc003a 100644 --- a/Dockerfile-CPU +++ b/Dockerfile-CPU @@ -9,7 +9,7 @@ RUN add-apt-repository ppa:deadsnakes/ppa RUN apt-get update && apt-get install -y python3.9 python3-pip libjpeg8-dev zlib1g-dev python3-dev libpython3.9-dev libffi-dev libgl1 RUN python3.9 -m pip install --upgrade pip # EXPLICITLY install cpu versions of torch/torchvision (not all versions have +cpu modes on PyPI...) -RUN python3.9 -m pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cpu +RUN python3.9 -m pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cpu RUN python3.9 -m pip install openvino-dev==2023.0.1 opencv-python-headless mlcube_docker # Do some dependency installation separately here to make layer caching more efficient diff --git a/Dockerfile-CUDA11.6 b/Dockerfile-CUDA11.8 similarity index 92% rename from Dockerfile-CUDA11.6 rename to Dockerfile-CUDA11.8 index db052592e..d8eb30b1a 100644 --- a/Dockerfile-CUDA11.6 +++ b/Dockerfile-CUDA11.8 @@ -1,4 +1,4 @@ -FROM nvidia/cuda:11.6.2-devel-ubuntu20.04 +FROM nvidia/cuda:11.8.0-devel-ubuntu20.04 LABEL github="https://github.com/mlcommons/GaNDLF" LABEL docs="https://mlcommons.github.io/GaNDLF/" LABEL version=1.0 @@ -12,7 +12,7 @@ RUN apt-get update && apt-get install -y software-properties-common RUN add-apt-repository ppa:deadsnakes/ppa RUN apt-get update && apt-get install -y python3.9 python3-pip libjpeg8-dev zlib1g-dev python3-dev libpython3.9-dev libffi-dev libgl1 RUN python3.9 -m pip install --upgrade pip -RUN python3.9 -m pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116 +RUN python3.9 -m pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118 RUN python3.9 -m pip install openvino-dev==2023.0.1 opencv-python-headless mlcube_docker # Do some dependency installation separately here to make layer caching more efficient diff --git a/Dockerfile-ROCm b/Dockerfile-ROCm index 9bbdaaa2b..81c0b04b3 100644 --- a/Dockerfile-ROCm +++ b/Dockerfile-ROCm @@ -1,4 +1,4 @@ -FROM rocm/pytorch:rocm5.2.3_ubuntu20.04_py3.7_pytorch_1.12.1 +FROM rocm/pytorch:rocm5.6_ubuntu20.04_py3.8_pytorch_1.12.1 LABEL github="https://github.com/mlcommons/GaNDLF" LABEL docs="https://mlcommons.github.io/GaNDLF/" LABEL version=1.0 @@ -10,7 +10,7 @@ RUN apt-get update && apt-get install -y software-properties-common RUN add-apt-repository ppa:deadsnakes/ppa RUN apt-get update && apt-get install -y python3.9 python3-pip libjpeg8-dev zlib1g-dev python3-dev libpython3.9-dev libffi-dev libgl1 RUN python3.9 -m pip install --upgrade pip -RUN python3.9 -m pip install torch==1.13.1+rocm5.2 torchvision==0.14.1+rocm5.2 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/rocm5.2 +RUN python3.9 -m pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/rocm5.6 RUN python3.9 -m pip install --upgrade pip && python3.9 -m pip install openvino-dev==2023.0.1 opencv-python-headless mlcube_docker RUN apt-get update && apt-get install -y libgl1 diff --git a/GANDLF/cli/__init__.py b/GANDLF/cli/__init__.py index d86d6a88f..7021caa4b 100644 --- a/GANDLF/cli/__init__.py +++ b/GANDLF/cli/__init__.py @@ -13,5 +13,5 @@ "Contact: gandlf@mlcommons.org\n\n" + "This program is NOT FDA/CE approved and NOT intended for clinical use.\nCopyright (c) " + str(date.today().year) - + " MLCommons. All rights reserved.\n\nCitation: https://arxiv.org/abs/2103.01006" + + " MLCommons. All rights reserved.\n\nCitation: https://doi.org/10.1038/s44172-023-00066-3" ) diff --git a/GANDLF/cli/preprocess_and_save.py b/GANDLF/cli/preprocess_and_save.py index 82bc4f574..1da202ae7 100644 --- a/GANDLF/cli/preprocess_and_save.py +++ b/GANDLF/cli/preprocess_and_save.py @@ -105,15 +105,13 @@ def preprocess_and_save( # the "squeeze" is needed because the dataloader automatically # constructs 5D tensor considering the batch_size as first # dimension, but the constructor needs 4D tensor. - subject_process[str(channel)] = torchio.Image( + subject_process[str(channel)] = torchio.ScalarImage( tensor=subject[str(channel)]["data"].squeeze(0), - type=torchio.INTENSITY, path=subject[str(channel)]["path"], ) if parameters["headers"]["labelHeader"] is not None: - subject_process["label"] = torchio.Image( + subject_process["label"] = torchio.LabelMap( tensor=subject["label"]["data"].squeeze(0), - type=torchio.LABEL, path=subject["label"]["path"], ) subject_dict_to_write = torchio.Subject(subject_process) diff --git a/GANDLF/compute/forward_pass.py b/GANDLF/compute/forward_pass.py index 0adcc5fb3..82cebdaa4 100644 --- a/GANDLF/compute/forward_pass.py +++ b/GANDLF/compute/forward_pass.py @@ -129,12 +129,12 @@ def validate_network( subject_dict = {} label_ground_truth = None label_present = False - # this is when we want the dataloader to pick up properties of GaNDLF's DataLoader, such as pre-processing and augmentations, if appropriate + # this is when we want the dataloader to pick up properties of GaNDLF's + # DataLoader, such as pre-processing and augmentations, if appropriate if "label" in subject: if subject["label"] != ["NA"]: - subject_dict["label"] = torchio.Image( + subject_dict["label"] = torchio.LabelMap( path=subject["label"]["path"], - type=torchio.LABEL, tensor=subject["label"]["data"].squeeze(0), affine=subject["label"]["affine"].squeeze(0), ) @@ -149,9 +149,8 @@ def validate_network( ) for key in params["channel_keys"]: - subject_dict[key] = torchio.Image( + subject_dict[key] = torchio.ScalarImage( path=subject[key]["path"], - type=subject[key]["type"], tensor=subject[key]["data"].squeeze(0), affine=subject[key]["affine"].squeeze(0), ) @@ -320,8 +319,7 @@ def validate_network( output_prediction = aggregator.get_output_tensor() output_prediction = output_prediction.unsqueeze(0) if params["save_output"]: - img_for_metadata = torchio.Image( - type=subject["1"]["type"], + img_for_metadata = torchio.ScalarImage( tensor=subject["1"]["data"].squeeze(0), affine=subject["1"]["affine"].squeeze(0), ).as_sitk() diff --git a/GANDLF/data/augmentation/noise_enhanced.py b/GANDLF/data/augmentation/noise_enhanced.py index 2a9a21e17..41fb6ed74 100644 --- a/GANDLF/data/augmentation/noise_enhanced.py +++ b/GANDLF/data/augmentation/noise_enhanced.py @@ -59,8 +59,8 @@ def get_params( mean_range: Tuple[float, float], std_range: Tuple[float, float], ) -> Tuple[float, float]: - mean = self.sample_uniform(*mean_range).item() - std = self.sample_uniform(*std_range).item() + mean = self.sample_uniform(*mean_range) + std = self.sample_uniform(*std_range) seed = self._get_random_seed() return mean, std, seed diff --git a/GANDLF/data/patch_miner/opm/utils.py b/GANDLF/data/patch_miner/opm/utils.py index 9c66118a8..53bf3605b 100644 --- a/GANDLF/data/patch_miner/opm/utils.py +++ b/GANDLF/data/patch_miner/opm/utils.py @@ -10,8 +10,9 @@ from skimage.morphology import remove_small_holes from skimage.color.colorconv import rgb2hsv import cv2 -#from skimage.exposure import rescale_intensity -#from skimage.color import rgb2hed + +# from skimage.exposure import rescale_intensity +# from skimage.color import rgb2hed # import matplotlib.pyplot as plt import yaml @@ -238,7 +239,8 @@ def alpha_rgb_2d_channel_check(img): else: return False -#def pen_marking_check(img, intensity_thresh=225, intensity_thresh_saturation =50, intensity_thresh_b = 128): + +# def pen_marking_check(img, intensity_thresh=225, intensity_thresh_saturation =50, intensity_thresh_b = 128): # """ # This function is used to curate patches from the input image. It is used to remove patches that have pen markings. # Args: @@ -259,7 +261,14 @@ def alpha_rgb_2d_channel_check(img): # #Assume patch is valid # return True -def patch_artifact_check(img, intensity_thresh = 250, intensity_thresh_saturation = 5, intensity_thresh_b = 128, patch_size = (256,256)): + +def patch_artifact_check( + img, + intensity_thresh=250, + intensity_thresh_saturation=5, + intensity_thresh_b=128, + patch_size=(256, 256), +): """ This function is used to curate patches from the input image. It is used to remove patches that are mostly background. Args: @@ -271,23 +280,36 @@ def patch_artifact_check(img, intensity_thresh = 250, intensity_thresh_saturatio Returns: bool: Whether the patch is valid (True) or not (False) """ - #patch_size = config["patch_size"] + # patch_size = config["patch_size"] patch_hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) count_white_pixels = np.sum(np.logical_and.reduce(img > intensity_thresh, axis=2)) percent_pixels = count_white_pixels / (patch_size[0] * patch_size[1]) count_black_pixels = np.sum(np.logical_and.reduce(img < intensity_thresh_b, axis=2)) percent_pixel_b = count_black_pixels / (patch_size[0] * patch_size[1]) - percent_pixel_2 = np.sum(patch_hsv[...,1] < intensity_thresh_saturation) / (patch_size[0] * patch_size[1]) - percent_pixel_3 = np.sum(patch_hsv[...,2] > intensity_thresh) / (patch_size[0] * patch_size[1]) + percent_pixel_2 = np.sum(patch_hsv[..., 1] < intensity_thresh_saturation) / ( + patch_size[0] * patch_size[1] + ) + percent_pixel_3 = np.sum(patch_hsv[..., 2] > intensity_thresh) / ( + patch_size[0] * patch_size[1] + ) - if percent_pixel_2 > 0.99 or np.mean(patch_hsv[...,1]) < 5 or percent_pixel_3 > 0.99: + if ( + percent_pixel_2 > 0.99 + or np.mean(patch_hsv[..., 1]) < 5 + or percent_pixel_3 > 0.99 + ): if percent_pixel_2 < 0.1: return False - elif (percent_pixel_2 > 0.99 and percent_pixel_3 > 0.99) or percent_pixel_b > 0.99 or percent_pixels > 0.9: + elif ( + (percent_pixel_2 > 0.99 and percent_pixel_3 > 0.99) + or percent_pixel_b > 0.99 + or percent_pixels > 0.9 + ): return False # assume that the patch is valid return True + def parse_config(config_file): """ Parse config file and return a dictionary of config values. @@ -304,7 +326,7 @@ def parse_config(config_file): config["value_map"] = config.get("value_map", None) config["read_type"] = config.get("read_type", "random") config["overlap_factor"] = config.get("overlap_factor", 0.0) - config["patch_size"] = config.get("patch_size", [256,256]) + config["patch_size"] = config.get("patch_size", [256, 256]) return config diff --git a/GANDLF/metrics/classification.py b/GANDLF/metrics/classification.py index 842dc88f4..ec4e9d160 100644 --- a/GANDLF/metrics/classification.py +++ b/GANDLF/metrics/classification.py @@ -64,9 +64,7 @@ def overall_stats(predictions, ground_truth, params): "aucroc": tm.AUROC( task=task, num_classes=params["model"]["num_classes"], - average=average_type_key - if average_type_key != "micro" - else "macro", + average=average_type_key if average_type_key != "micro" else "macro", ), } for metric_name, calculator in calculators.items(): diff --git a/GANDLF/metrics/generic.py b/GANDLF/metrics/generic.py index 34b197df7..1c90a3a20 100644 --- a/GANDLF/metrics/generic.py +++ b/GANDLF/metrics/generic.py @@ -15,9 +15,7 @@ ) -def generic_function_output_with_check( - predicted_classes, label, metric_function -): +def generic_function_output_with_check(predicted_classes, label, metric_function): if torch.min(predicted_classes) < 0: print( "WARNING: Negative values detected in prediction, cannot compute torchmetrics calculations." @@ -32,16 +30,12 @@ def generic_function_output_with_check( max_clamp_val = metric_function.num_classes - 1 except AttributeError: max_clamp_val = 1 - predicted_new = torch.clamp( - predicted_classes.cpu().int(), max=max_clamp_val - ) + predicted_new = torch.clamp(predicted_classes.cpu().int(), max=max_clamp_val) predicted_new = predicted_new.reshape(label.shape) return metric_function(predicted_new, label.cpu().int()) -def generic_torchmetrics_score( - output, label, metric_class, metric_key, params -): +def generic_torchmetrics_score(output, label, metric_class, metric_key, params): task = determine_classification_task_type(params) num_classes = params["model"]["num_classes"] predicted_classes = output @@ -67,9 +61,7 @@ def recall_score(output, label, params): def precision_score(output, label, params): - return generic_torchmetrics_score( - output, label, Precision, "precision", params - ) + return generic_torchmetrics_score(output, label, Precision, "precision", params) def f1_score(output, label, params): @@ -77,15 +69,11 @@ def f1_score(output, label, params): def accuracy(output, label, params): - return generic_torchmetrics_score( - output, label, Accuracy, "accuracy", params - ) + return generic_torchmetrics_score(output, label, Accuracy, "accuracy", params) def specificity_score(output, label, params): - return generic_torchmetrics_score( - output, label, Specificity, "specificity", params - ) + return generic_torchmetrics_score(output, label, Specificity, "specificity", params) def iou_score(output, label, params): diff --git a/GANDLF/utils/generic.py b/GANDLF/utils/generic.py index 050cce4ff..52f6a33d9 100644 --- a/GANDLF/utils/generic.py +++ b/GANDLF/utils/generic.py @@ -49,7 +49,9 @@ def checkPatchDivisibility(patch_size, number=16): return True -def determine_classification_task_type(params: Dict[str, Union[Dict[str, Any], Any]]) -> str: +def determine_classification_task_type( + params: Dict[str, Union[Dict[str, Any], Any]] +) -> str: """Determine the task (binary or multiclass) from the model config. Args: params (dict): The parameter dictionary containing training and data information. @@ -159,10 +161,7 @@ def checkPatchDimensions(patch_size, numlay): patch_size_to_check = patch_size_to_check[:-1] if all( - [ - x >= 2 ** (numlay + 1) and x % 2**numlay == 0 - for x in patch_size_to_check - ] + [x >= 2 ** (numlay + 1) and x % 2**numlay == 0 for x in patch_size_to_check] ): return numlay else: @@ -198,9 +197,7 @@ def get_array_from_image_or_tensor(input_tensor_or_image): elif isinstance(input_tensor_or_image, np.ndarray): return input_tensor_or_image else: - raise ValueError( - "Input must be a torch.Tensor or sitk.Image or np.ndarray" - ) + raise ValueError("Input must be a torch.Tensor or sitk.Image or np.ndarray") def set_determinism(seed=42): @@ -270,9 +267,7 @@ def __update_metric_from_list_to_single_string(input_metrics_dict) -> dict: output_metrics_dict = deepcopy(cohort_level_metrics) for metric in metrics_dict_from_parameters: if isinstance(sample_level_metrics[metric], np.ndarray): - to_print = ( - sample_level_metrics[metric] / length_of_dataloader - ).tolist() + to_print = (sample_level_metrics[metric] / length_of_dataloader).tolist() else: to_print = sample_level_metrics[metric] / length_of_dataloader output_metrics_dict[metric] = to_print @@ -315,7 +310,5 @@ def define_multidim_average_type_key(params, metric_name) -> str: Returns: str: The average type key. """ - average_type_key = params["metrics"][metric_name].get( - "multidim_average", "global" - ) + average_type_key = params["metrics"][metric_name].get("multidim_average", "global") return average_type_key diff --git a/docs/setup.md b/docs/setup.md index 0ce038e01..2a76dbc7a 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -28,18 +28,20 @@ GaNDLF's primary computational foundation is built on PyTorch, and as such it su (base) $> conda create -n venv_gandlf python=3.9 -y (base) $> conda activate venv_gandlf (venv_gandlf) $> ### subsequent commands go here -### PyTorch installation - https://pytorch.org/get-started/previous-versions/#v1131 -## CUDA 11.6 -# (venv_gandlf) $> pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116 -## ROCm -# (venv_gandlf) $> pip install torch==1.13.1+rocm5.2 torchvision==0.14.1+rocm5.2 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/rocm5.2 +### PyTorch installation - https://pytorch.org/get-started/previous-versions/#v210 +## CUDA 12.1 +# (venv_gandlf) $> pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu121 +## CUDA 11.8 +# (venv_gandlf) $> pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118 +## ROCm 5.6 +# (venv_gandlf) $> pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/rocm5.6 ## CPU-only -# (venv_gandlf) $> pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cpu +# (venv_gandlf) $> pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0 --extra-index-url https://download.pytorch.org/whl/cpu ``` ### Optional Dependencies -The following dependencies are optional, and are needed for specific features of GaNDLF. +The following dependencies are **optional**, and are only needed to access specific features of GaNDLF. ```bash (venv_gandlf) $> pip install openvino-dev==2023.0.1 # [OPTIONAL] to generate post-training optimized models for inference diff --git a/docs/usage.md b/docs/usage.md index 80cdf088a..cc0c3e52d 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -236,7 +236,7 @@ GaNDLF provides a script to generate metrics after an inference process is done. # -h, --help Show help message and exit # -v, --version Show program's version number and exit. -c , --config The configuration file (contains all the information related to the training/inference session) - -i , --inputdata CSV file that is used to generate the metrics; should contain 3 columns: 'subjectid, prediction, target' + -i , --inputdata CSV file that is used to generate the metrics; should contain 3 columns: 'SubjectID,Target,Prediction' -o , --outputfile Location to save the output dictionary. If not provided, will print to stdout. ``` diff --git a/gandlf_generateMetrics b/gandlf_generateMetrics index 81a1051ae..a25d663d6 100644 --- a/gandlf_generateMetrics +++ b/gandlf_generateMetrics @@ -32,7 +32,7 @@ if __name__ == "__main__": metavar="", type=str, required=True, - help="CSV file that is used to generate the metrics; should contain 3 columns: 'subjectid, prediction, target'", + help="The CSV file of input data that is used to generate the metrics; should contain 3 columns: 'SubjectID,Target,Prediction'", ) parser.add_argument( "-o", diff --git a/mlcube/model_mlcube/mlcube.yaml b/mlcube/model_mlcube/mlcube.yaml index 1d3704be7..a2cddab5a 100644 --- a/mlcube/model_mlcube/mlcube.yaml +++ b/mlcube/model_mlcube/mlcube.yaml @@ -30,7 +30,7 @@ docker: # Docker build context relative to $MLCUBE_ROOT. (gandlf_deploy can handle this automatically.) build_context: "../" # Docker file name within docker build context. Any "Dockerfile-*" in the GaNDLF source repo is valid. - build_file: "Dockerfile-CUDA11.6" + build_file: "Dockerfile-CUDA11.8" # These settings should be set by global MLCube configuration, generally not per-deployment. # However, some sane defaults (for Docker >19.03) are here: diff --git a/setup.py b/setup.py index 55ef5d747..76abfbeda 100644 --- a/setup.py +++ b/setup.py @@ -81,7 +81,7 @@ def run(self): requirements = [ - "torch==1.13.1", + "torch==2.1.0", "black==23.11.0", "numpy==1.25.0", "scipy", @@ -89,7 +89,7 @@ def run(self): "SimpleITK!=2.2.1", # https://github.com/mlcommons/GaNDLF/issues/536 "torchvision", "tqdm", - "torchio==0.18.75", + "torchio==0.19.3", "pandas>=2.0.0", "scikit-learn>=0.23.2", "scikit-image>=0.19.1", @@ -110,7 +110,7 @@ def run(self): "pydicom", "onnx", "torchinfo==1.7.0", - "segmentation-models-pytorch==0.3.2", + "segmentation-models-pytorch==0.3.3", "ACSConv==0.1.1", "docker", "dicom-anonymizer", @@ -125,7 +125,7 @@ def run(self): version=__version__, author="MLCommons", author_email="gandlf@mlcommons.org", - python_requires=">=3.9, <3.11", + python_requires=">3.8, <3.12", packages=find_packages( where=os.path.dirname(os.path.abspath(__file__)), exclude=toplevel_package_excludes, @@ -157,6 +157,7 @@ def run(self): "Operating System :: OS Independent", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Scientific/Engineering :: Medical Science Apps.", ], description=(