Skip to content

Commit 0f73d95

Browse files
committed
Merge branch 'dev' of github.com:Project-MONAI/MONAI into fix-6056-wsireader-defaults
2 parents 5ae1822 + 7baf282 commit 0f73d95

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1719
-494
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ Examples and notebook tutorials are located at [Project-MONAI/tutorials](https:/
5151

5252
Technical documentation is available at [docs.monai.io](https://docs.monai.io).
5353

54+
## Citation
55+
56+
If you have used MONAI in your research, please cite us! The citation can be exported from: https://arxiv.org/abs/2211.02701.
57+
5458
## Model Zoo
5559
[The MONAI Model Zoo](https://github.com/Project-MONAI/model-zoo) is a place for researchers and data scientists to share the latest and great models from the community.
5660
Utilizing [the MONAI Bundle format](https://docs.monai.io/en/latest/bundle_intro.html) makes it easy to [get started](https://github.com/Project-MONAI/tutorials/tree/main/model_zoo) building workflows with MONAI.

docs/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-f https://download.pytorch.org/whl/cpu/torch-1.12.1%2Bcpu-cp37-cp37m-linux_x86_64.whl
22
torch>=1.8
3-
pytorch-ignite==0.4.10
3+
pytorch-ignite==0.4.11
44
numpy>=1.20
55
itk>=5.2
66
nibabel

docs/source/MONAI-logo-color.png

20.5 KB
Loading

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def generate_apidocs(*args):
116116
"collapse_navigation": True,
117117
"navigation_depth": 3,
118118
"show_toc_level": 1,
119-
"footer_items": ["copyright"],
119+
"footer_start": ["copyright"],
120120
"navbar_align": "content",
121121
"logo": {"image_light": "MONAI-logo-color.png", "image_dark": "MONAI-logo-color.png"},
122122
}

docs/source/transforms.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ Generic Interfaces
8888
.. autoclass:: RandomOrder
8989
:members:
9090

91+
Functionals
92+
-----------
93+
94+
Crop and Pad (functional)
95+
^^^^^^^^^^^^^^^^^^^^^^^^^
96+
.. automodule:: monai.transforms.croppad.functional
97+
:members:
98+
99+
Spatial (functional)
100+
^^^^^^^^^^^^^^^^^^^^
101+
.. automodule:: monai.transforms.spatial.functional
102+
:members:
103+
104+
.. currentmodule:: monai.transforms
105+
91106
Vanilla Transforms
92107
------------------
93108

monai/apps/pathology/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def compute_isolated_tumor_cells(tumor_mask: np.ndarray, threshold: float) -> li
5252
A region with the longest diameter less than this threshold is considered as an ITC.
5353
"""
5454
max_label = np.amax(tumor_mask)
55-
properties = measure.regionprops(tumor_mask, coordinates="rc")
55+
properties = measure.regionprops(tumor_mask)
5656
itc_list = [i + 1 for i in range(max_label) if properties[i].major_axis_length < threshold]
5757

5858
return itc_list

monai/apps/utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,15 @@ def get_logger(
5858
(https://docs.python.org/3/library/logging.html#formatter-objects).
5959
`logger_handler` can be used to add an additional handler.
6060
"""
61+
adds_stdout_handler = module_name is not None and module_name not in logging.root.manager.loggerDict
6162
logger = logging.getLogger(module_name)
6263
logger.propagate = False
6364
logger.setLevel(logging.INFO)
64-
handler = logging.StreamHandler(sys.stdout)
65-
formatter = logging.Formatter(fmt=fmt, datefmt=datefmt)
66-
handler.setFormatter(formatter)
67-
logger.addHandler(handler)
65+
if adds_stdout_handler: # don't add multiple stdout or add to the root
66+
handler = logging.StreamHandler(sys.stdout)
67+
formatter = logging.Formatter(fmt=fmt, datefmt=datefmt)
68+
handler.setFormatter(formatter)
69+
logger.addHandler(handler)
6870
if logger_handler is not None:
6971
logger.addHandler(logger_handler)
7072
return logger

monai/bundle/scripts.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ def run(
617617
**override: Any,
618618
) -> list:
619619
"""
620-
Specify `meta_file` and `config_file` to run monai bundle components and workflows.
620+
Specify `config_file` to run monai bundle components and workflows.
621621
622622
Typical usage examples:
623623
@@ -642,10 +642,12 @@ def run(
642642
Args:
643643
runner_id: ID name of the expected config expression to run, can also be a list of IDs to run in order.
644644
meta_file: filepath of the metadata file, if it is a list of file paths, the content of them will be merged.
645+
Default to "configs/metadata.json", which is commonly used for bundles in MONAI model zoo.
645646
config_file: filepath of the config file, if `None`, must be provided in `args_file`.
646647
if it is a list of file paths, the content of them will be merged.
647-
logging_file: config file for `logging` module in the program, default to `None`. for more details:
648+
logging_file: config file for `logging` module in the program. for more details:
648649
https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig.
650+
Default to "configs/logging.conf", which is commonly used for bundles in MONAI model zoo.
649651
tracking: enable the experiment tracking feature at runtime with optionally configurable and extensible.
650652
if "mlflow", will add `MLFlowHandler` to the parsed bundle with default logging settings,
651653
if other string, treat it as file path to load the logging settings, if `dict`,
@@ -719,18 +721,30 @@ def run(
719721
warnings.warn("`config_file` not provided for 'monai.bundle run'.")
720722
_log_input_summary(tag="run", args=_args)
721723
config_file_, meta_file_, runner_id_, logging_file_, tracking_ = _pop_args(
722-
_args, config_file=None, meta_file=None, runner_id="", logging_file=None, tracking=None
724+
_args,
725+
config_file=None,
726+
meta_file="configs/metadata.json",
727+
runner_id="",
728+
logging_file="configs/logging.conf",
729+
tracking=None,
723730
)
724731
if logging_file_ is not None:
725732
if not os.path.exists(logging_file_):
726-
raise FileNotFoundError(f"can't find the logging config file: {logging_file_}.")
727-
logger.info(f"set logging properties based on config: {logging_file_}.")
728-
fileConfig(logging_file_, disable_existing_loggers=False)
733+
if logging_file_ == "configs/logging.conf":
734+
warnings.warn("default logging file in 'configs/logging.conf' not exists, skip logging.")
735+
else:
736+
raise FileNotFoundError(f"can't find the logging config file: {logging_file_}.")
737+
else:
738+
logger.info(f"set logging properties based on config: {logging_file_}.")
739+
fileConfig(logging_file_, disable_existing_loggers=False)
729740

730741
parser = ConfigParser()
731742
parser.read_config(f=config_file_)
732743
if meta_file_ is not None:
733-
parser.read_meta(f=meta_file_)
744+
if not os.path.exists(meta_file_):
745+
warnings.warn("default meta file in 'configs/metadata.json' not exists.")
746+
else:
747+
parser.read_meta(f=meta_file_)
734748

735749
# the rest key-values in the _args are to override config content
736750
parser.update(pairs=_args)

monai/data/image_reader.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,9 @@ class NrrdReader(ImageReader):
15221522
dtype: dtype of the data array when loading image.
15231523
index_order: Specify whether the returned data array should be in C-order (‘C’) or Fortran-order (‘F’).
15241524
Numpy is usually in C-order, but default on the NRRD header is F
1525+
affine_lps_to_ras: whether to convert the affine matrix from "LPS" to "RAS". Defaults to ``True``.
1526+
Set to ``True`` to be consistent with ``NibabelReader``, otherwise the affine matrix is unmodified.
1527+
15251528
kwargs: additional args for `nrrd.read` API. more details about available args:
15261529
https://github.com/mhe/pynrrd/blob/master/nrrd/reader.py
15271530
@@ -1532,11 +1535,13 @@ def __init__(
15321535
channel_dim: int | None = None,
15331536
dtype: np.dtype | type | str | None = np.float32,
15341537
index_order: str = "F",
1538+
affine_lps_to_ras: bool = True,
15351539
**kwargs,
15361540
):
15371541
self.channel_dim = channel_dim
15381542
self.dtype = dtype
15391543
self.index_order = index_order
1544+
self.affine_lps_to_ras = affine_lps_to_ras
15401545
self.kwargs = kwargs
15411546

15421547
def verify_suffix(self, filename: Sequence[PathLike] | PathLike) -> bool:
@@ -1590,7 +1595,10 @@ def get_data(self, img: NrrdImage | list[NrrdImage]) -> tuple[np.ndarray, dict]:
15901595
if self.index_order == "C":
15911596
header = self._convert_f_to_c_order(header)
15921597
header[MetaKeys.ORIGINAL_AFFINE] = self._get_affine(i)
1593-
header = self._switch_lps_ras(header)
1598+
1599+
if self.affine_lps_to_ras:
1600+
header = self._switch_lps_ras(header)
1601+
15941602
header[MetaKeys.AFFINE] = header[MetaKeys.ORIGINAL_AFFINE].copy()
15951603
header[MetaKeys.SPATIAL_SHAPE] = header["sizes"]
15961604
[header.pop(k) for k in ("sizes", "space origin", "space directions")] # rm duplicated data in header

monai/data/meta_tensor.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ def affine(self) -> torch.Tensor:
461461
@affine.setter
462462
def affine(self, d: NdarrayTensor) -> None:
463463
"""Set the affine."""
464-
self.meta[MetaKeys.AFFINE] = torch.as_tensor(d, device=torch.device("cpu"), dtype=torch.double)
464+
self.meta[MetaKeys.AFFINE] = torch.as_tensor(d, device=torch.device("cpu"), dtype=torch.float64)
465465

466466
@property
467467
def pixdim(self):
@@ -471,7 +471,10 @@ def pixdim(self):
471471
return affine_to_spacing(self.affine)
472472

473473
def peek_pending_shape(self):
474-
"""Get the currently expected spatial shape as if all the pending operations are executed."""
474+
"""
475+
Get the currently expected spatial shape as if all the pending operations are executed.
476+
For tensors that have more than 3 spatial dimensions, only the shapes of the top 3 dimensions will be returned.
477+
"""
475478
res = None
476479
if self.pending_operations:
477480
res = self.pending_operations[-1].get(LazyAttr.SHAPE, None)
@@ -480,11 +483,13 @@ def peek_pending_shape(self):
480483

481484
def peek_pending_affine(self):
482485
res = self.affine
486+
r = len(res) - 1
483487
for p in self.pending_operations:
484-
next_matrix = convert_to_tensor(p.get(LazyAttr.AFFINE))
488+
next_matrix = convert_to_tensor(p.get(LazyAttr.AFFINE), dtype=torch.float64)
485489
if next_matrix is None:
486490
continue
487491
res = convert_to_dst_type(res, next_matrix)[0]
492+
next_matrix = monai.data.utils.to_affine_nd(r, next_matrix)
488493
res = monai.transforms.lazy.utils.combine_transforms(res, next_matrix)
489494
return res
490495

0 commit comments

Comments
 (0)