Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.

**Environment (please complete the following information; e.g. using `sh runtests.sh -v`):**
- OS
- Python version
- MONAI version [e.g. git commit hash]
- CUDA/cuDNN version
- GPU models and configuration
**Environment**

Ensuring you use the relevant python executable, please paste the output of:

```
python -c 'import monai; monai.config.print_debug_info()'
```

**Additional context**
Add any other context about the problem here.
3 changes: 3 additions & 0 deletions .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ jobs:
- name: Run quick tests (CPU ${{ runner.os }})
run: |
python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))'
python -c "import monai; monai.config.print_config()"
python -m unittest -v
env:
QUICKTEST: True
Expand Down Expand Up @@ -145,6 +146,7 @@ jobs:
- name: Run quick tests (CPU ${{ runner.os }})
run: |
python -c 'import torch; print(torch.__version__); print(torch.rand(5,3))'
python -c "import monai; monai.config.print_config()"
python -m tests.min_tests
env:
QUICKTEST: True
Expand Down Expand Up @@ -230,6 +232,7 @@ jobs:
echo $CUDA_VISIBLE_DEVICES
python -c "import torch; print(torch.__version__); print('{} of GPUs available'.format(torch.cuda.device_count()))"
python -c 'import torch; print(torch.rand(5,3, device=torch.device("cuda:0")))'
python -c "import monai; monai.config.print_config()"
BUILD_MONAI=1 ./runtests.sh --quick
if [ ${{ matrix.environment }} == "PT16+CUDA110" ]; then
# test the clang-format tool downloading once
Expand Down
4 changes: 2 additions & 2 deletions docs/source/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ Since MONAI v0.2.0, the extras syntax such as `pip install 'monai[nibabel]'` is

- The options are
```
[nibabel, skimage, pillow, tensorboard, gdown, ignite, torchvision, itk, tqdm, lmdb]
[nibabel, skimage, pillow, tensorboard, gdown, ignite, torchvision, itk, tqdm, lmdb, psutil]
```
which correspond to `nibabel`, `scikit-image`, `pillow`, `tensorboard`,
`gdown`, `pytorch-ignite`, `torchvision`, `itk`, and `tqdm` respectively.
`gdown`, `pytorch-ignite`, `torchvision`, `itk`, `tqdm`, `lmdb` and `psutil`, respectively.

- `pip install 'monai[all]'` installs all the optional dependencies.
6 changes: 4 additions & 2 deletions monai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
PY_REQUIRED_MAJOR = 3
PY_REQUIRED_MINOR = 6

__version__ = get_versions()["version"]
del get_versions
version_dict = get_versions()
__version__ = version_dict.get("version", "0+unknown")
__revision_id__ = version_dict.get("full-revisionid", None)
del get_versions, version_dict

__copyright__ = "(c) 2020 MONAI Consortium"

Expand Down
182 changes: 70 additions & 112 deletions monai/config/deviceconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,70 +11,15 @@

import os
import platform
import re
import sys
from collections import OrderedDict

import numpy as np
import torch

import monai
from monai.utils import OptionalImportError, optional_import

try:
import ignite

ignite_version = ignite.__version__
del ignite
except (ImportError, AttributeError):
ignite_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import nibabel

nibabel_version = nibabel.__version__
del nibabel
except (ImportError, AttributeError):
nibabel_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import skimage

skimage_version = skimage.__version__
del skimage
except (ImportError, AttributeError):
skimage_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import PIL

PIL_version = PIL.__version__
del PIL
except (ImportError, AttributeError):
PIL_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import tensorboard

tensorboard_version = tensorboard.__version__
del tensorboard
except (ImportError, AttributeError):
tensorboard_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import gdown

gdown_version = gdown.__version__
del gdown
except (ImportError, AttributeError):
gdown_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import torchvision

torchvision_version = torchvision.__version__
del torchvision
except (ImportError, AttributeError):
torchvision_version = "NOT INSTALLED or UNKNOWN VERSION."
from monai.utils import OptionalImportError, get_package_version, optional_import

try:
import itk # type: ignore
Expand All @@ -84,31 +29,14 @@
except (ImportError, AttributeError):
itk_version = "NOT INSTALLED or UNKNOWN VERSION."

try:
import tqdm

tqdm_version = tqdm.__version__
del tqdm
except (ImportError, AttributeError):
tqdm_version = "NOT INSTALLED or UNKNOWN VERSION."


try:
import lmdb # type: ignore

lmdb_version = lmdb.__version__
del lmdb
except (ImportError, AttributeError):
lmdb_version = "NOT INSTALLED or UNKNOWN VERSION."


try:
_, HAS_EXT = optional_import("monai._C")
USE_COMPILED = HAS_EXT and os.getenv("BUILD_MONAI", "0") == "1"
except (OptionalImportError, ImportError, AttributeError):
HAS_EXT = USE_COMPILED = False

psutil, has_psutil = optional_import("psutil")
psutil_version = psutil.__version__ if has_psutil else "NOT INSTALLED or UNKNOWN VERSION."


def get_config_values():
Expand All @@ -118,8 +46,6 @@ def get_config_values():
output = OrderedDict()

output["MONAI"] = monai.__version__
output["Python"] = sys.version.replace("\n", " ")
output["OS"] = f"{platform.system()} ({platform.release()})"
output["Numpy"] = np.version.full_version
output["Pytorch"] = torch.__version__

Expand All @@ -132,16 +58,17 @@ def get_optional_config_values():
"""
output = OrderedDict()

output["Pytorch Ignite"] = ignite_version
output["Nibabel"] = nibabel_version
output["scikit-image"] = skimage_version
output["Pillow"] = PIL_version
output["Tensorboard"] = tensorboard_version
output["gdown"] = gdown_version
output["TorchVision"] = torchvision_version
output["Pytorch Ignite"] = get_package_version("ignite")
output["Nibabel"] = get_package_version("nibabel")
output["scikit-image"] = get_package_version("skimage")
output["Pillow"] = get_package_version("PIL")
output["Tensorboard"] = get_package_version("tensorboard")
output["gdown"] = get_package_version("gdown")
output["TorchVision"] = get_package_version("torchvision")
output["ITK"] = itk_version
output["tqdm"] = tqdm_version
output["lmdb"] = lmdb_version
output["tqdm"] = get_package_version("tqdm")
output["lmdb"] = get_package_version("lmdb")
output["psutil"] = psutil_version

return output

Expand All @@ -156,6 +83,7 @@ def print_config(file=sys.stdout):
for k, v in get_config_values().items():
print(f"{k} version: {v}", file=file, flush=True)
print(f"MONAI flags: HAS_EXT = {HAS_EXT}, USE_COMPILED = {USE_COMPILED}")
print(f"MONAI rev id: {monai.__revision_id__}")

print("\nOptional dependencies:", file=file, flush=True)
for k, v in get_optional_config_values().items():
Expand Down Expand Up @@ -187,37 +115,58 @@ def _dict_append(in_dict, key, fn):
in_dict[key] = "UNKNOWN for given OS"


def get_system_info(file=sys.stdout) -> OrderedDict:
def get_system_info() -> OrderedDict:
"""
Get system info as an ordered dictionary.
"""
output: OrderedDict = OrderedDict()

_dict_append(output, "System", lambda: platform.system())
if output["System"] == "Windows":
_dict_append(output, "Win32 version", lambda: platform.win32_ver())
_dict_append(output, "Win32 edition", lambda: platform.win32_edition())
elif output["System"] == "Darwin":
_dict_append(output, "Mac version", lambda: platform.mac_ver()[0])
else:
linux_ver = re.search(r'PRETTY_NAME="(.*)"', open("/etc/os-release", "r").read())
if linux_ver:
_dict_append(output, "Linux version", lambda: linux_ver.group(1))

_dict_append(output, "Platform", lambda: platform.platform())
_dict_append(output, "Processor", lambda: platform.processor())
_dict_append(output, "Machine", lambda: platform.machine())
_dict_append(output, "Python version", lambda: platform.python_version())

if not has_psutil:
print("`psutil` required for `get_system_info", file=file, flush=True)
return output

p = psutil.Process()
with p.oneshot():
_dict_append(output, "Process name", lambda: p.name())
_dict_append(output, "Command", lambda: p.cmdline())
_dict_append(output, "Open files", lambda: p.open_files())
_dict_append(output, "Num physical CPUs", lambda: psutil.cpu_count(logical=False))
_dict_append(output, "Num logical CPUs", lambda: psutil.cpu_count(logical=True))
_dict_append(output, "Num usable CPUs", lambda: len(psutil.Process().cpu_affinity()))
_dict_append(output, "CPU usage (%)", lambda: psutil.cpu_percent(percpu=True))
_dict_append(output, "CPU freq. (MHz)", lambda: round(psutil.cpu_freq(percpu=False)[0]))
_dict_append(
output,
"Load avg. in last 1, 5, 15 mins (%)",
lambda: [round(x / psutil.cpu_count() * 100, 1) for x in psutil.getloadavg()],
)
_dict_append(output, "Disk usage (%)", lambda: psutil.disk_usage(os.getcwd()).percent)
_dict_append(
output,
"Avg. sensor temp. (°C)",
lambda: np.mean([item.current for sublist in psutil.sensors_temperatures().values() for item in sublist]),
)
_dict_append(output, "`psutil` missing", lambda: "run `pip install monai[psutil]`")
else:
p = psutil.Process()
with p.oneshot():
_dict_append(output, "Process name", lambda: p.name())
_dict_append(output, "Command", lambda: p.cmdline())
_dict_append(output, "Open files", lambda: p.open_files())
_dict_append(output, "Num physical CPUs", lambda: psutil.cpu_count(logical=False))
_dict_append(output, "Num logical CPUs", lambda: psutil.cpu_count(logical=True))
_dict_append(output, "Num usable CPUs", lambda: len(psutil.Process().cpu_affinity()))
_dict_append(output, "CPU usage (%)", lambda: psutil.cpu_percent(percpu=True))
_dict_append(output, "CPU freq. (MHz)", lambda: round(psutil.cpu_freq(percpu=False)[0]))
_dict_append(
output,
"Load avg. in last 1, 5, 15 mins (%)",
lambda: [round(x / psutil.cpu_count() * 100, 1) for x in psutil.getloadavg()],
)
_dict_append(output, "Disk usage (%)", lambda: psutil.disk_usage(os.getcwd()).percent)
_dict_append(
output,
"Avg. sensor temp. (Celsius)",
lambda: round(
np.mean([item.current for sublist in psutil.sensors_temperatures().values() for item in sublist], 1)
),
)
mem = psutil.virtual_memory()
_dict_append(output, "Total physical memory (GB)", lambda: round(mem.total / 1024 ** 3, 1))
_dict_append(output, "Available memory (GB)", lambda: round(mem.available / 1024 ** 3, 1))
_dict_append(output, "Used memory (GB)", lambda: round(mem.used / 1024 ** 3, 1))

return output

Expand All @@ -232,7 +181,7 @@ def print_system_info(file=sys.stdout) -> None:
if not has_psutil:
print("`psutil` required for `print_system_info`", file=file, flush=True)
else:
for k, v in get_system_info(file).items():
for k, v in get_system_info().items():
print(f"{k}: {v}", file=file, flush=True)


Expand All @@ -242,6 +191,15 @@ def get_gpu_info() -> OrderedDict:

num_gpus = torch.cuda.device_count()
_dict_append(output, "Num GPUs", lambda: num_gpus)

_dict_append(output, "Has CUDA", lambda: bool(torch.cuda.is_available()))
if output["Has CUDA"]:
_dict_append(output, "CUDA version", lambda: torch.version.cuda)
cudnn_ver = torch.backends.cudnn.version()
_dict_append(output, "cuDNN enabled", lambda: bool(cudnn_ver))
if cudnn_ver:
_dict_append(output, "cuDNN version", lambda: cudnn_ver)

if num_gpus > 0:
_dict_append(output, "Current device", lambda: torch.cuda.current_device())
_dict_append(output, "Library compiled for CUDA architectures", lambda: torch.cuda.get_arch_list())
Expand Down
21 changes: 21 additions & 0 deletions monai/utils/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"load_submodules",
"get_full_type_name",
"has_option",
"get_package_version",
]


Expand Down Expand Up @@ -231,3 +232,23 @@ def has_option(obj, keywords: Union[str, Sequence[str]]) -> bool:
if key not in sig.parameters:
return False
return True


def get_package_version(dep_name, default="NOT INSTALLED or UNKNOWN VERSION."):
"""
Try to load package and get version. If not found, return `default`.

If the package was already loaded, leave it. If wasn't previously loaded, unload it.
"""
dep_ver = default
dep_already_loaded = dep_name not in sys.modules

dep, has_dep = optional_import(dep_name)
if has_dep:
if hasattr(dep, "__version__"):
dep_ver = dep.__version__
# if not previously loaded, unload it
if not dep_already_loaded:
del dep
del sys.modules[dep_name]
return dep_ver
23 changes: 23 additions & 0 deletions tests/test_print_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2020 MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest

from monai.config import print_debug_info


class TestPrintInfo(unittest.TestCase):
def test_print_info(self):
print_debug_info()


if __name__ == "__main__":
unittest.main()