We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
DatasetSummary Min and Max on image foreground
### Discussed in https://github.com/Project-MONAI/MONAI/discussions/3819

<div type='discussions-op-text'>

<sup>Originally posted by **NabJa** February 18, 2022</sup>
Hello MONAI community,

In the [DatasetSummary ](https://github.com/Project-MONAI/MONAI/blob/dev/monai/data/dataset_summary.py#L28) class the min and max voxel intensities are computed on the whole image ([here](https://github.com/Project-MONAI/MONAI/blob/dev/monai/data/dataset_summary.py#L143)).  
However, in the nnUNet implementation of the DatasetAnalyzer does extract min and max voxel intensities ([here](https://github.com/MIC-DKFZ/nnUNet/blob/master/nnunet/experiment_planning/DatasetAnalyzer.py#L195)) only on the foreground (see [foreground extraction](https://github.com/MIC-DKFZ/nnUNet/blob/master/nnunet/experiment_planning/DatasetAnalyzer.py#L188)).

Shouldn't the min and max extraction of the voxels be moved to after the foreground extraction?

Thanks in advance for your opinions!
Nabil</div>

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `monai/data/dataset_summary.py`
Content:
```
1 # Copyright (c) MONAI Consortium
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 #     http://www.apache.org/licenses/LICENSE-2.0
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11 
12 from itertools import chain
13 from typing import List, Optional
14 
15 import numpy as np
16 import torch
17 
18 from monai.config import KeysCollection
19 from monai.data.dataloader import DataLoader
20 from monai.data.dataset import Dataset
21 from monai.transforms import concatenate
22 from monai.utils import convert_data_type
23 from monai.utils.enums import PostFix
24 
25 DEFAULT_POST_FIX = PostFix.meta()
26 
27 
28 class DatasetSummary:
29     """
30     This class provides a way to calculate a reasonable output voxel spacing according to
31     the input dataset. The achieved values can used to resample the input in 3d segmentation tasks
32     (like using as the `pixdim` parameter in `monai.transforms.Spacingd`).
33     In addition, it also supports to count the mean, std, min and max intensities of the input,
34     and these statistics are helpful for image normalization
35     (like using in `monai.transforms.ScaleIntensityRanged` and `monai.transforms.NormalizeIntensityd`).
36 
37     The algorithm for calculation refers to:
38     `Automated Design of Deep Learning Methods for Biomedical Image Segmentation <https://arxiv.org/abs/1904.08128>`_.
39 
40     """
41 
42     def __init__(
43         self,
44         dataset: Dataset,
45         image_key: Optional[str] = "image",
46         label_key: Optional[str] = "label",
47         meta_key: Optional[KeysCollection] = None,
48         meta_key_postfix: str = DEFAULT_POST_FIX,
49         num_workers: int = 0,
50         **kwargs,
51     ):
52         """
53         Args:
54             dataset: dataset from which to load the data.
55             image_key: key name of images (default: ``image``).
56             label_key: key name of labels (default: ``label``).
57             meta_key: explicitly indicate the key of the corresponding meta data dictionary.
58                 for example, for data with key `image`, the metadata by default is in `image_meta_dict`.
59                 the meta data is a dictionary object which contains: filename, affine, original_shape, etc.
60                 if None, will try to construct meta_keys by `{image_key}_{meta_key_postfix}`.
61             meta_key_postfix: use `{image_key}_{meta_key_postfix}` to fetch the meta data from dict,
62                 the meta data is a dictionary object (default: ``meta_dict``).
63             num_workers: how many subprocesses to use for data loading.
64                 ``0`` means that the data will be loaded in the main process (default: ``0``).
65             kwargs: other parameters (except `batch_size` and `num_workers`) for DataLoader,
66                 this class forces to use ``batch_size=1``.
67 
68         """
69 
70         self.data_loader = DataLoader(dataset=dataset, batch_size=1, num_workers=num_workers, **kwargs)
71 
72         self.image_key = image_key
73         self.label_key = label_key
74         self.meta_key = meta_key or f"{image_key}_{meta_key_postfix}"
75         self.all_meta_data: List = []
76 
77     def collect_meta_data(self):
78         """
79         This function is used to collect the meta data for all images of the dataset.
80         """
81 
82         for data in self.data_loader:
83             if self.meta_key not in data:
84                 raise ValueError(f"To collect meta data for the dataset, key `{self.meta_key}` must exist in `data`.")
85             self.all_meta_data.append(data[self.meta_key])
86 
87     def get_target_spacing(self, spacing_key: str = "pixdim", anisotropic_threshold: int = 3, percentile: float = 10.0):
88         """
89         Calculate the target spacing according to all spacings.
90         If the target spacing is very anisotropic,
91         decrease the spacing value of the maximum axis according to percentile.
92         So far, this function only supports NIFTI images which store spacings in headers with key "pixdim".
93         After loading with `monai.DataLoader`, "pixdim" is in the form of `torch.Tensor` with size `(batch_size, 8)`.
94 
95         Args:
96             spacing_key: key of spacing in meta data (default: ``pixdim``).
97             anisotropic_threshold: threshold to decide if the target spacing is anisotropic (default: ``3``).
98             percentile: for anisotropic target spacing, use the percentile of all spacings of the anisotropic axis to
99                 replace that axis.
100 
101         """
102         if len(self.all_meta_data) == 0:
103             self.collect_meta_data()
104         if spacing_key not in self.all_meta_data[0]:
105             raise ValueError("The provided spacing_key is not in self.all_meta_data.")
106         all_spacings = concatenate(to_cat=[data[spacing_key][:, 1:4] for data in self.all_meta_data], axis=0)
107         all_spacings, *_ = convert_data_type(data=all_spacings, output_type=np.ndarray, wrap_sequence=True)
108 
109         target_spacing = np.median(all_spacings, axis=0)
110         if max(target_spacing) / min(target_spacing) >= anisotropic_threshold:
111             largest_axis = np.argmax(target_spacing)
112             target_spacing[largest_axis] = np.percentile(all_spacings[:, largest_axis], percentile)
113 
114         output = list(target_spacing)
115 
116         return tuple(output)
117 
118     def calculate_statistics(self, foreground_threshold: int = 0):
119         """
120         This function is used to calculate the maximum, minimum, mean and standard deviation of intensities of
121         the input dataset.
122 
123         Args:
124             foreground_threshold: the threshold to distinguish if a voxel belongs to foreground, this parameter
125                 is used to select the foreground of images for calculation. Normally, `label > 0` means the corresponding
126                 voxel belongs to foreground, thus if you need to calculate the statistics for whole images, you can set
127                 the threshold to ``-1`` (default: ``0``).
128 
129         """
130         voxel_sum = torch.as_tensor(0.0)
131         voxel_square_sum = torch.as_tensor(0.0)
132         voxel_max, voxel_min = [], []
133         voxel_ct = 0
134 
135         for data in self.data_loader:
136             if self.image_key and self.label_key:
137                 image, label = data[self.image_key], data[self.label_key]
138             else:
139                 image, label = data
140             image, *_ = convert_data_type(data=image, output_type=torch.Tensor)
141             label, *_ = convert_data_type(data=label, output_type=torch.Tensor)
142 
143             voxel_max.append(image.max().item())
144             voxel_min.append(image.min().item())
145 
146             image_foreground = image[torch.where(label > foreground_threshold)]
147             voxel_ct += len(image_foreground)
148             voxel_sum += image_foreground.sum()
149             voxel_square_sum += torch.square(image_foreground).sum()
150 
151         self.data_max, self.data_min = max(voxel_max), min(voxel_min)
152         self.data_mean = (voxel_sum / voxel_ct).item()
153         self.data_std = (torch.sqrt(voxel_square_sum / voxel_ct - self.data_mean**2)).item()
154 
155     def calculate_percentiles(
156         self,
157         foreground_threshold: int = 0,
158         sampling_flag: bool = True,
159         interval: int = 10,
160         min_percentile: float = 0.5,
161         max_percentile: float = 99.5,
162     ):
163         """
164         This function is used to calculate the percentiles of intensities (and median) of the input dataset. To get
165         the required values, all voxels need to be accumulated. To reduce the memory used, this function can be set
166         to accumulate only a part of the voxels.
167 
168         Args:
169             foreground_threshold: the threshold to distinguish if a voxel belongs to foreground, this parameter
170                 is used to select the foreground of images for calculation. Normally, `label > 0` means the corresponding
171                 voxel belongs to foreground, thus if you need to calculate the statistics for whole images, you can set
172                 the threshold to ``-1`` (default: ``0``).
173             sampling_flag: whether to sample only a part of the voxels (default: ``True``).
174             interval: the sampling interval for accumulating voxels (default: ``10``).
175             min_percentile: minimal percentile (default: ``0.5``).
176             max_percentile: maximal percentile (default: ``99.5``).
177 
178         """
179         all_intensities = []
180         for data in self.data_loader:
181             if self.image_key and self.label_key:
182                 image, label = data[self.image_key], data[self.label_key]
183             else:
184                 image, label = data
185             image, *_ = convert_data_type(data=image, output_type=torch.Tensor)
186             label, *_ = convert_data_type(data=label, output_type=torch.Tensor)
187 
188             intensities = image[torch.where(label > foreground_threshold)].tolist()
189             if sampling_flag:
190                 intensities = intensities[::interval]
191             all_intensities.append(intensities)
192 
193         all_intensities = list(chain(*all_intensities))
194         self.data_min_percentile, self.data_max_percentile = np.percentile(
195             all_intensities, [min_percentile, max_percentile]
196         )
197         self.data_median = np.median(all_intensities)
198
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/monai/data/dataset_summary.py b/monai/data/dataset_summary.py
--- a/monai/data/dataset_summary.py
+++ b/monai/data/dataset_summary.py
@@ -140,10 +140,10 @@
             image, *_ = convert_data_type(data=image, output_type=torch.Tensor)
             label, *_ = convert_data_type(data=label, output_type=torch.Tensor)
 
-            voxel_max.append(image.max().item())
-            voxel_min.append(image.min().item())
-
             image_foreground = image[torch.where(label > foreground_threshold)]
+
+            voxel_max.append(image_foreground.max().item())
+            voxel_min.append(image_foreground.min().item())
             voxel_ct += len(image_foreground)
             voxel_sum += image_foreground.sum()
             voxel_square_sum += torch.square(image_foreground).sum()

{"golden_diff": "diff --git a/monai/data/dataset_summary.py b/monai/data/dataset_summary.py\n--- a/monai/data/dataset_summary.py\n+++ b/monai/data/dataset_summary.py\n@@ -140,10 +140,10 @@\n             image, *_ = convert_data_type(data=image, output_type=torch.Tensor)\n             label, *_ = convert_data_type(data=label, output_type=torch.Tensor)\n \n-            voxel_max.append(image.max().item())\n-            voxel_min.append(image.min().item())\n-\n             image_foreground = image[torch.where(label > foreground_threshold)]\n+\n+            voxel_max.append(image_foreground.max().item())\n+            voxel_min.append(image_foreground.min().item())\n             voxel_ct += len(image_foreground)\n             voxel_sum += image_foreground.sum()\n             voxel_square_sum += torch.square(image_foreground).sum()\n", "issue": "DatasetSummary Min and Max on image foreground\n### Discussed in https://github.com/Project-MONAI/MONAI/discussions/3819\r\n\r\n<div type='discussions-op-text'>\r\n\r\n<sup>Originally posted by **NabJa** February 18, 2022</sup>\r\nHello MONAI community,\r\n\r\nIn the [DatasetSummary ](https://github.com/Project-MONAI/MONAI/blob/dev/monai/data/dataset_summary.py#L28) class the min and max voxel intensities are computed on the whole image ([here](https://github.com/Project-MONAI/MONAI/blob/dev/monai/data/dataset_summary.py#L143)).  \r\nHowever, in the nnUNet implementation of the DatasetAnalyzer does extract min and max voxel intensities ([here](https://github.com/MIC-DKFZ/nnUNet/blob/master/nnunet/experiment_planning/DatasetAnalyzer.py#L195)) only on the foreground (see [foreground extraction](https://github.com/MIC-DKFZ/nnUNet/blob/master/nnunet/experiment_planning/DatasetAnalyzer.py#L188)).\r\n\r\nShouldn't the min and max extraction of the voxels be moved to after the foreground extraction?\r\n\r\nThanks in advance for your opinions!\r\nNabil</div>\n", "before_files": [{"content": "# Copyright (c) MONAI Consortium\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#     http://www.apache.org/licenses/LICENSE-2.0\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom itertools import chain\nfrom typing import List, Optional\n\nimport numpy as np\nimport torch\n\nfrom monai.config import KeysCollection\nfrom monai.data.dataloader import DataLoader\nfrom monai.data.dataset import Dataset\nfrom monai.transforms import concatenate\nfrom monai.utils import convert_data_type\nfrom monai.utils.enums import PostFix\n\nDEFAULT_POST_FIX = PostFix.meta()\n\n\nclass DatasetSummary:\n    \"\"\"\n    This class provides a way to calculate a reasonable output voxel spacing according to\n    the input dataset. The achieved values can used to resample the input in 3d segmentation tasks\n    (like using as the `pixdim` parameter in `monai.transforms.Spacingd`).\n    In addition, it also supports to count the mean, std, min and max intensities of the input,\n    and these statistics are helpful for image normalization\n    (like using in `monai.transforms.ScaleIntensityRanged` and `monai.transforms.NormalizeIntensityd`).\n\n    The algorithm for calculation refers to:\n    `Automated Design of Deep Learning Methods for Biomedical Image Segmentation <https://arxiv.org/abs/1904.08128>`_.\n\n    \"\"\"\n\n    def __init__(\n        self,\n        dataset: Dataset,\n        image_key: Optional[str] = \"image\",\n        label_key: Optional[str] = \"label\",\n        meta_key: Optional[KeysCollection] = None,\n        meta_key_postfix: str = DEFAULT_POST_FIX,\n        num_workers: int = 0,\n        **kwargs,\n    ):\n        \"\"\"\n        Args:\n            dataset: dataset from which to load the data.\n            image_key: key name of images (default: ``image``).\n            label_key: key name of labels (default: ``label``).\n            meta_key: explicitly indicate the key of the corresponding meta data dictionary.\n                for example, for data with key `image`, the metadata by default is in `image_meta_dict`.\n                the meta data is a dictionary object which contains: filename, affine, original_shape, etc.\n                if None, will try to construct meta_keys by `{image_key}_{meta_key_postfix}`.\n            meta_key_postfix: use `{image_key}_{meta_key_postfix}` to fetch the meta data from dict,\n                the meta data is a dictionary object (default: ``meta_dict``).\n            num_workers: how many subprocesses to use for data loading.\n                ``0`` means that the data will be loaded in the main process (default: ``0``).\n            kwargs: other parameters (except `batch_size` and `num_workers`) for DataLoader,\n                this class forces to use ``batch_size=1``.\n\n        \"\"\"\n\n        self.data_loader = DataLoader(dataset=dataset, batch_size=1, num_workers=num_workers, **kwargs)\n\n        self.image_key = image_key\n        self.label_key = label_key\n        self.meta_key = meta_key or f\"{image_key}_{meta_key_postfix}\"\n        self.all_meta_data: List = []\n\n    def collect_meta_data(self):\n        \"\"\"\n        This function is used to collect the meta data for all images of the dataset.\n        \"\"\"\n\n        for data in self.data_loader:\n            if self.meta_key not in data:\n                raise ValueError(f\"To collect meta data for the dataset, key `{self.meta_key}` must exist in `data`.\")\n            self.all_meta_data.append(data[self.meta_key])\n\n    def get_target_spacing(self, spacing_key: str = \"pixdim\", anisotropic_threshold: int = 3, percentile: float = 10.0):\n        \"\"\"\n        Calculate the target spacing according to all spacings.\n        If the target spacing is very anisotropic,\n        decrease the spacing value of the maximum axis according to percentile.\n        So far, this function only supports NIFTI images which store spacings in headers with key \"pixdim\".\n        After loading with `monai.DataLoader`, \"pixdim\" is in the form of `torch.Tensor` with size `(batch_size, 8)`.\n\n        Args:\n            spacing_key: key of spacing in meta data (default: ``pixdim``).\n            anisotropic_threshold: threshold to decide if the target spacing is anisotropic (default: ``3``).\n            percentile: for anisotropic target spacing, use the percentile of all spacings of the anisotropic axis to\n                replace that axis.\n\n        \"\"\"\n        if len(self.all_meta_data) == 0:\n            self.collect_meta_data()\n        if spacing_key not in self.all_meta_data[0]:\n            raise ValueError(\"The provided spacing_key is not in self.all_meta_data.\")\n        all_spacings = concatenate(to_cat=[data[spacing_key][:, 1:4] for data in self.all_meta_data], axis=0)\n        all_spacings, *_ = convert_data_type(data=all_spacings, output_type=np.ndarray, wrap_sequence=True)\n\n        target_spacing = np.median(all_spacings, axis=0)\n        if max(target_spacing) / min(target_spacing) >= anisotropic_threshold:\n            largest_axis = np.argmax(target_spacing)\n            target_spacing[largest_axis] = np.percentile(all_spacings[:, largest_axis], percentile)\n\n        output = list(target_spacing)\n\n        return tuple(output)\n\n    def calculate_statistics(self, foreground_threshold: int = 0):\n        \"\"\"\n        This function is used to calculate the maximum, minimum, mean and standard deviation of intensities of\n        the input dataset.\n\n        Args:\n            foreground_threshold: the threshold to distinguish if a voxel belongs to foreground, this parameter\n                is used to select the foreground of images for calculation. Normally, `label > 0` means the corresponding\n                voxel belongs to foreground, thus if you need to calculate the statistics for whole images, you can set\n                the threshold to ``-1`` (default: ``0``).\n\n        \"\"\"\n        voxel_sum = torch.as_tensor(0.0)\n        voxel_square_sum = torch.as_tensor(0.0)\n        voxel_max, voxel_min = [], []\n        voxel_ct = 0\n\n        for data in self.data_loader:\n            if self.image_key and self.label_key:\n                image, label = data[self.image_key], data[self.label_key]\n            else:\n                image, label = data\n            image, *_ = convert_data_type(data=image, output_type=torch.Tensor)\n            label, *_ = convert_data_type(data=label, output_type=torch.Tensor)\n\n            voxel_max.append(image.max().item())\n            voxel_min.append(image.min().item())\n\n            image_foreground = image[torch.where(label > foreground_threshold)]\n            voxel_ct += len(image_foreground)\n            voxel_sum += image_foreground.sum()\n            voxel_square_sum += torch.square(image_foreground).sum()\n\n        self.data_max, self.data_min = max(voxel_max), min(voxel_min)\n        self.data_mean = (voxel_sum / voxel_ct).item()\n        self.data_std = (torch.sqrt(voxel_square_sum / voxel_ct - self.data_mean**2)).item()\n\n    def calculate_percentiles(\n        self,\n        foreground_threshold: int = 0,\n        sampling_flag: bool = True,\n        interval: int = 10,\n        min_percentile: float = 0.5,\n        max_percentile: float = 99.5,\n    ):\n        \"\"\"\n        This function is used to calculate the percentiles of intensities (and median) of the input dataset. To get\n        the required values, all voxels need to be accumulated. To reduce the memory used, this function can be set\n        to accumulate only a part of the voxels.\n\n        Args:\n            foreground_threshold: the threshold to distinguish if a voxel belongs to foreground, this parameter\n                is used to select the foreground of images for calculation. Normally, `label > 0` means the corresponding\n                voxel belongs to foreground, thus if you need to calculate the statistics for whole images, you can set\n                the threshold to ``-1`` (default: ``0``).\n            sampling_flag: whether to sample only a part of the voxels (default: ``True``).\n            interval: the sampling interval for accumulating voxels (default: ``10``).\n            min_percentile: minimal percentile (default: ``0.5``).\n            max_percentile: maximal percentile (default: ``99.5``).\n\n        \"\"\"\n        all_intensities = []\n        for data in self.data_loader:\n            if self.image_key and self.label_key:\n                image, label = data[self.image_key], data[self.label_key]\n            else:\n                image, label = data\n            image, *_ = convert_data_type(data=image, output_type=torch.Tensor)\n            label, *_ = convert_data_type(data=label, output_type=torch.Tensor)\n\n            intensities = image[torch.where(label > foreground_threshold)].tolist()\n            if sampling_flag:\n                intensities = intensities[::interval]\n            all_intensities.append(intensities)\n\n        all_intensities = list(chain(*all_intensities))\n        self.data_min_percentile, self.data_max_percentile = np.percentile(\n            all_intensities, [min_percentile, max_percentile]\n        )\n        self.data_median = np.median(all_intensities)\n", "path": "monai/data/dataset_summary.py"}], "after_files": [{"content": "# Copyright (c) MONAI Consortium\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#     http://www.apache.org/licenses/LICENSE-2.0\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom itertools import chain\nfrom typing import List, Optional\n\nimport numpy as np\nimport torch\n\nfrom monai.config import KeysCollection\nfrom monai.data.dataloader import DataLoader\nfrom monai.data.dataset import Dataset\nfrom monai.transforms import concatenate\nfrom monai.utils import convert_data_type\nfrom monai.utils.enums import PostFix\n\nDEFAULT_POST_FIX = PostFix.meta()\n\n\nclass DatasetSummary:\n    \"\"\"\n    This class provides a way to calculate a reasonable output voxel spacing according to\n    the input dataset. The achieved values can used to resample the input in 3d segmentation tasks\n    (like using as the `pixdim` parameter in `monai.transforms.Spacingd`).\n    In addition, it also supports to count the mean, std, min and max intensities of the input,\n    and these statistics are helpful for image normalization\n    (like using in `monai.transforms.ScaleIntensityRanged` and `monai.transforms.NormalizeIntensityd`).\n\n    The algorithm for calculation refers to:\n    `Automated Design of Deep Learning Methods for Biomedical Image Segmentation <https://arxiv.org/abs/1904.08128>`_.\n\n    \"\"\"\n\n    def __init__(\n        self,\n        dataset: Dataset,\n        image_key: Optional[str] = \"image\",\n        label_key: Optional[str] = \"label\",\n        meta_key: Optional[KeysCollection] = None,\n        meta_key_postfix: str = DEFAULT_POST_FIX,\n        num_workers: int = 0,\n        **kwargs,\n    ):\n        \"\"\"\n        Args:\n            dataset: dataset from which to load the data.\n            image_key: key name of images (default: ``image``).\n            label_key: key name of labels (default: ``label``).\n            meta_key: explicitly indicate the key of the corresponding meta data dictionary.\n                for example, for data with key `image`, the metadata by default is in `image_meta_dict`.\n                the meta data is a dictionary object which contains: filename, affine, original_shape, etc.\n                if None, will try to construct meta_keys by `{image_key}_{meta_key_postfix}`.\n            meta_key_postfix: use `{image_key}_{meta_key_postfix}` to fetch the meta data from dict,\n                the meta data is a dictionary object (default: ``meta_dict``).\n            num_workers: how many subprocesses to use for data loading.\n                ``0`` means that the data will be loaded in the main process (default: ``0``).\n            kwargs: other parameters (except `batch_size` and `num_workers`) for DataLoader,\n                this class forces to use ``batch_size=1``.\n\n        \"\"\"\n\n        self.data_loader = DataLoader(dataset=dataset, batch_size=1, num_workers=num_workers, **kwargs)\n\n        self.image_key = image_key\n        self.label_key = label_key\n        self.meta_key = meta_key or f\"{image_key}_{meta_key_postfix}\"\n        self.all_meta_data: List = []\n\n    def collect_meta_data(self):\n        \"\"\"\n        This function is used to collect the meta data for all images of the dataset.\n        \"\"\"\n\n        for data in self.data_loader:\n            if self.meta_key not in data:\n                raise ValueError(f\"To collect meta data for the dataset, key `{self.meta_key}` must exist in `data`.\")\n            self.all_meta_data.append(data[self.meta_key])\n\n    def get_target_spacing(self, spacing_key: str = \"pixdim\", anisotropic_threshold: int = 3, percentile: float = 10.0):\n        \"\"\"\n        Calculate the target spacing according to all spacings.\n        If the target spacing is very anisotropic,\n        decrease the spacing value of the maximum axis according to percentile.\n        So far, this function only supports NIFTI images which store spacings in headers with key \"pixdim\".\n        After loading with `monai.DataLoader`, \"pixdim\" is in the form of `torch.Tensor` with size `(batch_size, 8)`.\n\n        Args:\n            spacing_key: key of spacing in meta data (default: ``pixdim``).\n            anisotropic_threshold: threshold to decide if the target spacing is anisotropic (default: ``3``).\n            percentile: for anisotropic target spacing, use the percentile of all spacings of the anisotropic axis to\n                replace that axis.\n\n        \"\"\"\n        if len(self.all_meta_data) == 0:\n            self.collect_meta_data()\n        if spacing_key not in self.all_meta_data[0]:\n            raise ValueError(\"The provided spacing_key is not in self.all_meta_data.\")\n        all_spacings = concatenate(to_cat=[data[spacing_key][:, 1:4] for data in self.all_meta_data], axis=0)\n        all_spacings, *_ = convert_data_type(data=all_spacings, output_type=np.ndarray, wrap_sequence=True)\n\n        target_spacing = np.median(all_spacings, axis=0)\n        if max(target_spacing) / min(target_spacing) >= anisotropic_threshold:\n            largest_axis = np.argmax(target_spacing)\n            target_spacing[largest_axis] = np.percentile(all_spacings[:, largest_axis], percentile)\n\n        output = list(target_spacing)\n\n        return tuple(output)\n\n    def calculate_statistics(self, foreground_threshold: int = 0):\n        \"\"\"\n        This function is used to calculate the maximum, minimum, mean and standard deviation of intensities of\n        the input dataset.\n\n        Args:\n            foreground_threshold: the threshold to distinguish if a voxel belongs to foreground, this parameter\n                is used to select the foreground of images for calculation. Normally, `label > 0` means the corresponding\n                voxel belongs to foreground, thus if you need to calculate the statistics for whole images, you can set\n                the threshold to ``-1`` (default: ``0``).\n\n        \"\"\"\n        voxel_sum = torch.as_tensor(0.0)\n        voxel_square_sum = torch.as_tensor(0.0)\n        voxel_max, voxel_min = [], []\n        voxel_ct = 0\n\n        for data in self.data_loader:\n            if self.image_key and self.label_key:\n                image, label = data[self.image_key], data[self.label_key]\n            else:\n                image, label = data\n            image, *_ = convert_data_type(data=image, output_type=torch.Tensor)\n            label, *_ = convert_data_type(data=label, output_type=torch.Tensor)\n\n            image_foreground = image[torch.where(label > foreground_threshold)]\n\n            voxel_max.append(image_foreground.max().item())\n            voxel_min.append(image_foreground.min().item())\n            voxel_ct += len(image_foreground)\n            voxel_sum += image_foreground.sum()\n            voxel_square_sum += torch.square(image_foreground).sum()\n\n        self.data_max, self.data_min = max(voxel_max), min(voxel_min)\n        self.data_mean = (voxel_sum / voxel_ct).item()\n        self.data_std = (torch.sqrt(voxel_square_sum / voxel_ct - self.data_mean**2)).item()\n\n    def calculate_percentiles(\n        self,\n        foreground_threshold: int = 0,\n        sampling_flag: bool = True,\n        interval: int = 10,\n        min_percentile: float = 0.5,\n        max_percentile: float = 99.5,\n    ):\n        \"\"\"\n        This function is used to calculate the percentiles of intensities (and median) of the input dataset. To get\n        the required values, all voxels need to be accumulated. To reduce the memory used, this function can be set\n        to accumulate only a part of the voxels.\n\n        Args:\n            foreground_threshold: the threshold to distinguish if a voxel belongs to foreground, this parameter\n                is used to select the foreground of images for calculation. Normally, `label > 0` means the corresponding\n                voxel belongs to foreground, thus if you need to calculate the statistics for whole images, you can set\n                the threshold to ``-1`` (default: ``0``).\n            sampling_flag: whether to sample only a part of the voxels (default: ``True``).\n            interval: the sampling interval for accumulating voxels (default: ``10``).\n            min_percentile: minimal percentile (default: ``0.5``).\n            max_percentile: maximal percentile (default: ``99.5``).\n\n        \"\"\"\n        all_intensities = []\n        for data in self.data_loader:\n            if self.image_key and self.label_key:\n                image, label = data[self.image_key], data[self.label_key]\n            else:\n                image, label = data\n            image, *_ = convert_data_type(data=image, output_type=torch.Tensor)\n            label, *_ = convert_data_type(data=label, output_type=torch.Tensor)\n\n            intensities = image[torch.where(label > foreground_threshold)].tolist()\n            if sampling_flag:\n                intensities = intensities[::interval]\n            all_intensities.append(intensities)\n\n        all_intensities = list(chain(*all_intensities))\n        self.data_min_percentile, self.data_max_percentile = np.percentile(\n            all_intensities, [min_percentile, max_percentile]\n        )\n        self.data_median = np.median(all_intensities)\n", "path": "monai/data/dataset_summary.py"}]}