monai-weekly 1.5.dev2513__py3-none-any.whl → 1.5.dev2515__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
monai/bundle/scripts.py CHANGED
@@ -312,21 +312,6 @@ def _get_ngc_token(api_key, retry=0):
312
312
  return token
313
313
 
314
314
 
315
- def _get_latest_bundle_version_monaihosting(name):
316
- full_url = f"{MONAI_HOSTING_BASE_URL}/{name.lower()}"
317
- if has_requests:
318
- resp = requests.get(full_url)
319
- try:
320
- resp.raise_for_status()
321
- model_info = json.loads(resp.text)
322
- return model_info["model"]["latestVersionIdStr"]
323
- except requests.exceptions.HTTPError:
324
- # for monaihosting bundles, if cannot find the version, get from model zoo model_info.json
325
- return get_bundle_versions(name)["latest_version"]
326
-
327
- raise ValueError("NGC API requires requests package. Please install it.")
328
-
329
-
330
315
  def _examine_monai_version(monai_version: str) -> tuple[bool, str]:
331
316
  """Examine if the package version is compatible with the MONAI version in the metadata."""
332
317
  version_dict = get_versions()
@@ -430,7 +415,7 @@ def _get_latest_bundle_version(
430
415
  name = _add_ngc_prefix(name)
431
416
  return _get_latest_bundle_version_ngc(name)
432
417
  elif source == "monaihosting":
433
- return _get_latest_bundle_version_monaihosting(name)
418
+ return get_bundle_versions(name, repo="Project-MONAI/model-zoo", tag="dev")["latest_version"]
434
419
  elif source == "ngc_private":
435
420
  headers = kwargs.pop("headers", {})
436
421
  name = _add_ngc_prefix(name)
@@ -528,7 +513,9 @@ def download(
528
513
  If source is "ngc_private", you need specify the NGC_API_KEY in the environment variable.
529
514
  repo: repo name. This argument is used when `url` is `None` and `source` is "github" or "huggingface_hub".
530
515
  If `source` is "github", it should be in the form of "repo_owner/repo_name/release_tag".
531
- If `source` is "huggingface_hub", it should be in the form of "repo_owner/repo_name".
516
+ If `source` is "huggingface_hub", it should be in the form of "repo_owner/repo_name". Please note that
517
+ bundles for "monaihosting" source are also hosted on Hugging Face Hub, but the "repo_id" is always in the form
518
+ of "MONAI/bundle_name", therefore, this argument is not required for "monaihosting" source.
532
519
  If `source` is "ngc_private", it should be in the form of "org/org_name" or "org/org_name/team/team_name",
533
520
  or you can specify the environment variable NGC_ORG and NGC_TEAM.
534
521
  url: url to download the data. If not `None`, data will be downloaded directly
@@ -600,11 +587,15 @@ def download(
600
587
  _download_from_github(repo=repo_, download_path=bundle_dir_, filename=name_ver, progress=progress_)
601
588
  elif source_ == "monaihosting":
602
589
  try:
590
+ extract_path = os.path.join(bundle_dir_, name_)
591
+ huggingface_hub.snapshot_download(repo_id=f"MONAI/{name_}", revision=version_, local_dir=extract_path)
592
+ except (huggingface_hub.errors.RevisionNotFoundError, huggingface_hub.errors.RepositoryNotFoundError):
593
+ # if bundle or version not found from huggingface, download from ngc monaihosting
603
594
  _download_from_monaihosting(
604
595
  download_path=bundle_dir_, filename=name_, version=version_, progress=progress_
605
596
  )
606
597
  except urllib.error.HTTPError:
607
- # for monaihosting bundles, if cannot download from default host, download according to bundle_info
598
+ # if also cannot download from ngc monaihosting, download according to bundle_info
608
599
  _download_from_bundle_info(
609
600
  download_path=bundle_dir_, filename=name_, version=version_, progress=progress_
610
601
  )
@@ -139,21 +139,17 @@ def ifftn_centered_t(ksp: Tensor, spatial_dims: int, is_complex: bool = True) ->
139
139
  output2 = ifftn_centered(ksp, spatial_dims=2, is_complex=True)
140
140
  """
141
141
  # define spatial dims to perform ifftshift, fftshift, and ifft
142
- shift = list(range(-spatial_dims, 0))
142
+ dims = list(range(-spatial_dims, 0))
143
143
  if is_complex:
144
144
  if ksp.shape[-1] != 2:
145
145
  raise ValueError(f"ksp.shape[-1] is not 2 ({ksp.shape[-1]}).")
146
- shift = list(range(-spatial_dims - 1, -1))
147
- dims = list(range(-spatial_dims, 0))
148
-
149
- x = ifftshift(ksp, shift)
150
-
151
- if is_complex:
152
- x = torch.view_as_real(torch.fft.ifftn(torch.view_as_complex(x), dim=dims, norm="ortho"))
146
+ x = torch.view_as_complex(ifftshift(ksp, [d - 1 for d in dims]))
153
147
  else:
154
- x = torch.view_as_real(torch.fft.ifftn(x, dim=dims, norm="ortho"))
148
+ x = ifftshift(ksp, dims)
149
+
150
+ x = torch.view_as_real(torch.fft.ifftn(x, dim=dims, norm="ortho"))
155
151
 
156
- out: Tensor = fftshift(x, shift)
152
+ out: Tensor = fftshift(x, [d - 1 for d in dims])
157
153
 
158
154
  return out
159
155
 
@@ -187,20 +183,16 @@ def fftn_centered_t(im: Tensor, spatial_dims: int, is_complex: bool = True) -> T
187
183
  output2 = fftn_centered(im, spatial_dims=2, is_complex=True)
188
184
  """
189
185
  # define spatial dims to perform ifftshift, fftshift, and fft
190
- shift = list(range(-spatial_dims, 0))
186
+ dims = list(range(-spatial_dims, 0))
191
187
  if is_complex:
192
188
  if im.shape[-1] != 2:
193
189
  raise ValueError(f"img.shape[-1] is not 2 ({im.shape[-1]}).")
194
- shift = list(range(-spatial_dims - 1, -1))
195
- dims = list(range(-spatial_dims, 0))
196
-
197
- x = ifftshift(im, shift)
198
-
199
- if is_complex:
200
- x = torch.view_as_real(torch.fft.fftn(torch.view_as_complex(x), dim=dims, norm="ortho"))
190
+ x = torch.view_as_complex(ifftshift(im, [d - 1 for d in dims]))
201
191
  else:
202
- x = torch.view_as_real(torch.fft.fftn(x, dim=dims, norm="ortho"))
192
+ x = ifftshift(im, dims)
193
+
194
+ x = torch.view_as_real(torch.fft.fftn(x, dim=dims, norm="ortho"))
203
195
 
204
- out: Tensor = fftshift(x, shift)
196
+ out: Tensor = fftshift(x, [d - 1 for d in dims])
205
197
 
206
198
  return out
@@ -11,6 +11,7 @@
11
11
 
12
12
  from __future__ import annotations
13
13
 
14
+ import threading
14
15
  import warnings
15
16
  from collections.abc import Hashable, Mapping
16
17
  from contextlib import contextmanager
@@ -66,15 +67,41 @@ class TraceableTransform(Transform):
66
67
  The information in the stack of applied transforms must be compatible with the
67
68
  default collate, by only storing strings, numbers and arrays.
68
69
 
69
- `tracing` could be enabled by `self.set_tracing` or setting
70
+ `tracing` could be enabled by assigning to `self.tracing` or setting
70
71
  `MONAI_TRACE_TRANSFORM` when initializing the class.
71
72
  """
72
73
 
73
- tracing = MONAIEnvVars.trace_transform() != "0"
74
+ def _init_trace_threadlocal(self):
75
+ """Create a `_tracing` instance member to store the thread-local tracing state value."""
76
+ # needed since this class is meant to be a trait with no constructor
77
+ if not hasattr(self, "_tracing"):
78
+ self._tracing = threading.local()
79
+
80
+ # This is True while the above initialising _tracing is False when this is
81
+ # called from a different thread than the one initialising _tracing.
82
+ if not hasattr(self._tracing, "value"):
83
+ self._tracing.value = MONAIEnvVars.trace_transform() != "0"
84
+
85
+ def __getstate__(self):
86
+ """When pickling, remove the `_tracing` member from the output, if present, since it's not picklable."""
87
+ _dict = dict(getattr(self, "__dict__", {})) # this makes __dict__ always present in the unpickled object
88
+ _slots = {k: getattr(self, k) for k in getattr(self, "__slots__", [])}
89
+ _dict.pop("_tracing", None) # remove tracing
90
+ return _dict if len(_slots) == 0 else (_dict, _slots)
91
+
92
+ @property
93
+ def tracing(self) -> bool:
94
+ """
95
+ Returns the tracing state, which is thread-local and initialised to `MONAIEnvVars.trace_transform() != "0"`.
96
+ """
97
+ self._init_trace_threadlocal()
98
+ return bool(self._tracing.value)
74
99
 
75
- def set_tracing(self, tracing: bool) -> None:
76
- """Set whether to trace transforms."""
77
- self.tracing = tracing
100
+ @tracing.setter
101
+ def tracing(self, val: bool):
102
+ """Sets the thread-local tracing state to `val`."""
103
+ self._init_trace_threadlocal()
104
+ self._tracing.value = val
78
105
 
79
106
  @staticmethod
80
107
  def trace_key(key: Hashable = None):
@@ -291,7 +318,7 @@ class TraceableTransform(Transform):
291
318
 
292
319
  def get_most_recent_transform(self, data, key: Hashable = None, check: bool = True, pop: bool = False):
293
320
  """
294
- Get most recent transform for the stack.
321
+ Get most recent matching transform for the current class from the sequence of applied operations.
295
322
 
296
323
  Args:
297
324
  data: dictionary of data or `MetaTensor`.
@@ -316,9 +343,14 @@ class TraceableTransform(Transform):
316
343
  all_transforms = data.get(self.trace_key(key), MetaTensor.get_default_applied_operations())
317
344
  else:
318
345
  raise ValueError(f"`data` should be either `MetaTensor` or dictionary, got {type(data)}.")
346
+
347
+ if not all_transforms:
348
+ raise ValueError(f"Item of type {type(data)} (key: {key}, pop: {pop}) has empty 'applied_operations'")
349
+
319
350
  if check:
320
351
  self.check_transforms_match(all_transforms[-1])
321
- return all_transforms.pop() if pop else all_transforms[-1]
352
+
353
+ return all_transforms.pop(-1) if pop else all_transforms[-1]
322
354
 
323
355
  def pop_transform(self, data, key: Hashable = None, check: bool = True):
324
356
  """
monai/utils/misc.py CHANGED
@@ -546,7 +546,7 @@ class MONAIEnvVars:
546
546
 
547
547
  @staticmethod
548
548
  def algo_hash() -> str | None:
549
- return os.environ.get("MONAI_ALGO_HASH", "c108ea9")
549
+ return os.environ.get("MONAI_ALGO_HASH", "4c18daf")
550
550
 
551
551
  @staticmethod
552
552
  def trace_transform() -> str | None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: monai-weekly
3
- Version: 1.5.dev2513
3
+ Version: 1.5.dev2515
4
4
  Summary: AI Toolkit for Healthcare Imaging
5
5
  Home-page: https://monai.io/
6
6
  Author: MONAI Consortium
@@ -49,6 +49,7 @@ Requires-Dist: lmdb; extra == "all"
49
49
  Requires-Dist: psutil; extra == "all"
50
50
  Requires-Dist: cucim-cu12; (platform_system == "Linux" and python_version >= "3.9" and python_version <= "3.10") and extra == "all"
51
51
  Requires-Dist: openslide-python; extra == "all"
52
+ Requires-Dist: openslide-bin; extra == "all"
52
53
  Requires-Dist: tifffile; (platform_system == "Linux" or platform_system == "Darwin") and extra == "all"
53
54
  Requires-Dist: imagecodecs; (platform_system == "Linux" or platform_system == "Darwin") and extra == "all"
54
55
  Requires-Dist: pandas; extra == "all"
@@ -105,6 +106,7 @@ Provides-Extra: cucim
105
106
  Requires-Dist: cucim-cu12; (platform_system == "Linux" and python_version >= "3.9" and python_version <= "3.10") and extra == "cucim"
106
107
  Provides-Extra: openslide
107
108
  Requires-Dist: openslide-python; extra == "openslide"
109
+ Requires-Dist: openslide-bin; extra == "openslide"
108
110
  Provides-Extra: tifffile
109
111
  Requires-Dist: tifffile; (platform_system == "Linux" or platform_system == "Darwin") and extra == "tifffile"
110
112
  Provides-Extra: imagecodecs
@@ -1,5 +1,5 @@
1
- monai/__init__.py,sha256=lOVClDZxEDXvMXltT5kiFD_6UM2TYyLqp6gJRLLSWY8,4095
2
- monai/_version.py,sha256=TaZfkTv96TjOsFZhWyZwFaEDQWRV0aCQUaMZaKfJkOo,503
1
+ monai/__init__.py,sha256=cz2IbPvV5WFZb9B6iwGQYTcCSUfAkFQgg6Z7EyBu82E,4095
2
+ monai/_version.py,sha256=PvcDKbDCwlMsws9Aqn0bDOjHV15xcRqSmMGahjEBO5k,503
3
3
  monai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  monai/_extensions/__init__.py,sha256=NEBPreRhQ8H9gVvgrLr_y52_TmqB96u_u4VQmeNT93I,642
5
5
  monai/_extensions/loader.py,sha256=7SiKw36q-nOzH8CRbBurFrz7GM40GCu7rc93Tm8XpnI,3643
@@ -55,8 +55,9 @@ monai/apps/generation/maisi/networks/diffusion_model_unet_maisi.py,sha256=XFOiy6
55
55
  monai/apps/mmars/__init__.py,sha256=BolpgEi9jNBgrOQd3Kwp-9QQLeWQwQtlN_MJkK1eu5s,726
56
56
  monai/apps/mmars/mmars.py,sha256=24JylLuw-qTDsTnTK4Y5kAbF_nWdivrSRS8EMGy69oQ,13134
57
57
  monai/apps/mmars/model_desc.py,sha256=k7WSMRuyQN8xPax8aUmGKiTNZmcVatdqPYCgxDih-x4,9996
58
- monai/apps/nnunet/__init__.py,sha256=gyqmg1fxPf3RF6LL25gnpMTfNS14uxweuJ93e4UzjB8,745
58
+ monai/apps/nnunet/__init__.py,sha256=u_VSta8R-Ta0oKUxxzDKXo9BK6WL7kAsGPRee2Gp9GY,963
59
59
  monai/apps/nnunet/__main__.py,sha256=qrloBLymK98OPcaBKocrlF8io2h4mUuXJPFVLZT-XDo,832
60
+ monai/apps/nnunet/nnunet_bundle.py,sha256=ucqx9P2oDC0G5AYbNYwZvs4TgcoNVmOEIDTGZpi4jbw,24758
60
61
  monai/apps/nnunet/nnunetv2_runner.py,sha256=0VZTpzmjkOhamdqYGd9bhTdZcRDeOsMOBIjaW1Upi8w,48001
61
62
  monai/apps/nnunet/utils.py,sha256=OwLBcc0LZ_n7-ofE8EgkgmIHT23wq1xySCD6lphSjz0,6761
62
63
  monai/apps/nuclick/__init__.py,sha256=s9djSd6kvViPnFvMR11Dgd30Lv4oY6FaPJr4ZZJZLq0,573
@@ -114,7 +115,7 @@ monai/bundle/config_item.py,sha256=rMjXSGkjJZdi04BwSHwCcIwzIb_TflmC3xDhC3SVJRs,1
114
115
  monai/bundle/config_parser.py,sha256=cGyEn-cqNk0rEEZ1Qiv6UydmIDvtWZcMVljyfVm5i50,23025
115
116
  monai/bundle/properties.py,sha256=iN3K4FVmN9ny1Hw9p5j7_ULcCdSD8PmrR7qXxbNz49k,11582
116
117
  monai/bundle/reference_resolver.py,sha256=GXCMK4iogxxE6VocsmAbUrcXosmC5arnjeG9zYhHKpg,16748
117
- monai/bundle/scripts.py,sha256=VE3hIAcPfncbT1MGyLk0by1ZtA9jit6Hc7djrUUKUX8,91018
118
+ monai/bundle/scripts.py,sha256=69sZ_W9xQzuVnRL0Ma64Ac742UIe9iCvTKHwkuCU0a8,91064
118
119
  monai/bundle/utils.py,sha256=t-22uFvLn7Yy-dr1v1U33peNOxgAmU4TJiGAbsBrUKs,10108
119
120
  monai/bundle/workflows.py,sha256=CuhmFq1AWsN3ATiYJCSakPOxrOdGutl6vkpo9sxe8gU,34369
120
121
  monai/config/__init__.py,sha256=CN28CfTdsp301gv8YXfVvkbztCfbAqrLKrJi_C8oP9s,1048
@@ -263,7 +264,7 @@ monai/networks/blocks/dynunet_block.py,sha256=kg8NNTL4nBqsy6gBcxmS5ZCPxlhWM_iB0B
263
264
  monai/networks/blocks/encoder.py,sha256=NwH5VSQLwamJqrSbZSdQqMwZCk80CPbSpMGEE0r0Cwo,3669
264
265
  monai/networks/blocks/fcn.py,sha256=mnCMrxhUdj2yZ0DPIj0Xf9OKVdv-qhG1BpnAg5j7q6c,9024
265
266
  monai/networks/blocks/feature_pyramid_network.py,sha256=zHMXB_hl92kmuJIe0rTvQlzQn1W77WTQZ7XaoivktEw,10631
266
- monai/networks/blocks/fft_utils_t.py,sha256=8bOvhLgP5nDLz8QwzD4XnRaxE9-tGba2-b_QDK8IWSs,8263
267
+ monai/networks/blocks/fft_utils_t.py,sha256=rarC7BUw9TeawhDQESC5oJhPvbg_OFFNTa1HsNs3GKg,8017
267
268
  monai/networks/blocks/localnet_block.py,sha256=b2-ZZvkMPphHJZYTbwEZDhqA-mMBSFM5WQOoohk_6W4,11456
268
269
  monai/networks/blocks/mednext_block.py,sha256=GKaFkRvmho79yxwfYyeSaJtHFtk185dY0tA4_rPnsQA,10487
269
270
  monai/networks/blocks/mlp.py,sha256=qw_jgyrYwoQ5WYBM1rtSSaO4C837ZbctoRKhh_BQQFI,3341
@@ -357,7 +358,7 @@ monai/optimizers/utils.py,sha256=GVsJsZWO2aAP9IzwhXgca_9gUNHFClup6qG4ZFs42z4,413
357
358
  monai/transforms/__init__.py,sha256=-LmAa_W5fJxm5I_btvAONNebWe2exa7IWwcvYrNxzCc,16744
358
359
  monai/transforms/adaptors.py,sha256=LpYChldlOur-VFgu_nBIBze0J841-NWgf0UHvvHRNPU,8796
359
360
  monai/transforms/compose.py,sha256=EQPQkxdzrLoVvoeKVa8KABmB_Oc9pg-G0EsSS8aTraw,39189
360
- monai/transforms/inverse.py,sha256=Wg8UnMJru41G3eHGipUemAWziHGU-qdd-Flfi3eOpeo,18746
361
+ monai/transforms/inverse.py,sha256=BARCRaUYabIajmOfsyNbN47v1v0eQiFAU7Vyvz-IddU,20287
361
362
  monai/transforms/inverse_batch_transform.py,sha256=fMbukZq2P99BhqqMuWZFJ9uboZ5dN61MBvvicwf40V0,7055
362
363
  monai/transforms/nvtx.py,sha256=1EKEXZIhTUFKoIrJmd_fevwrHwo731dVFUFJQFiOk3w,3386
363
364
  monai/transforms/traits.py,sha256=F8kmhnekTyaAdo8wIFjO3-uqpVtmFym3mNxbYbyvkFI,3563
@@ -410,7 +411,7 @@ monai/utils/deprecate_utils.py,sha256=gKeEV4MsI51qeQ5gci2me_C-0e-tDwa3VZzd3XPQqL
410
411
  monai/utils/dist.py,sha256=7brB42CvdS8Jvr8Y7hfqov1uk6NNnYea9dYfgMYy0BY,8578
411
412
  monai/utils/enums.py,sha256=aupxnORUHqVPF2Ac5nxstsP5aIyewMoqgGb88D62yxg,19931
412
413
  monai/utils/jupyter_utils.py,sha256=BYtj80LWQAYg5RWPj5g4j2AMCzLECvAcnZdXns0Ruw8,15651
413
- monai/utils/misc.py,sha256=9-5zBIDSUYewzoQBkiBm0G_HR8hmwQCT-I15RYOQqEQ,31759
414
+ monai/utils/misc.py,sha256=M0oCfj55pZTrcYF0QgyS91JflqBwxSuNnOifl2HRSZk,31759
414
415
  monai/utils/module.py,sha256=R37PpCNCcHQvjjZFbNjNyzWb3FURaKLxQucjhzQk0eU,26087
415
416
  monai/utils/nvtx.py,sha256=i9JBxR1uhW1ZCgLPLlTx8b907QlXkFzJyTBLMlFjhtU,6876
416
417
  monai/utils/ordering.py,sha256=0nlA5b5QpVCHbtiCbTC-YsqjTmjm0bub0IeJhGFBOes,8270
@@ -425,7 +426,7 @@ monai/visualize/img2tensorboard.py,sha256=n4ztSa5BQAUxSTGvi2tp45v-F7-RNgSlbsdy-9
425
426
  monai/visualize/occlusion_sensitivity.py,sha256=OQHEJLyIhB8zWqQsfKaX-1kvCjWFVYtLfS4dFC0nKFI,18160
426
427
  monai/visualize/utils.py,sha256=B-MhTVs7sQbIqYS3yPnpBwPw2K82rE2PBtGIfpwZtWM,9894
427
428
  monai/visualize/visualizer.py,sha256=qckyaMZCbezYUwE20k5yc-Pb7UozVavMDbrmyQwfYHY,1377
428
- monai_weekly-1.5.dev2513.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
429
+ monai_weekly-1.5.dev2515.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
429
430
  tests/apps/__init__.py,sha256=s9djSd6kvViPnFvMR11Dgd30Lv4oY6FaPJr4ZZJZLq0,573
430
431
  tests/apps/test_auto3dseg_bundlegen.py,sha256=FpTJo9Lfe8vdhGuWeZ9y1BQmqYwTt-s8mDVtoLGAz_I,5594
431
432
  tests/apps/test_check_hash.py,sha256=MuZslW2DDCxHKEo6-PiL7hnbxGuZRRYf6HOh3ZQv1qQ,1761
@@ -507,7 +508,7 @@ tests/apps/vista3d/test_vista3d_sampler.py,sha256=-luQCe3Hhle2PC9AkFCUgK8gozOD0O
507
508
  tests/apps/vista3d/test_vista3d_transforms.py,sha256=nAPiDBNWeXLoW7ax3HHL63t5jqzQ3HFa-6wTvdyqVJk,3280
508
509
  tests/bundle/__init__.py,sha256=s9djSd6kvViPnFvMR11Dgd30Lv4oY6FaPJr4ZZJZLq0,573
509
510
  tests/bundle/test_bundle_ckpt_export.py,sha256=VnpigCoBAAc2lo0rWOpVMg0IYGB6vbHXL8xLtB1Pkio,4622
510
- tests/bundle/test_bundle_download.py,sha256=sM6bIaCjIdDbHWpMigYx4T7qFLXSeexnRpGubUKbx9U,20404
511
+ tests/bundle/test_bundle_download.py,sha256=QaQOde6MCpUeHhoYNTd1GjDQmT0j01kTMw53qocOzxQ,20695
511
512
  tests/bundle/test_bundle_get_data.py,sha256=lQh321mev_7fsLXRg0Tq5uEjuQILethDHRKzB6VV0o4,3667
512
513
  tests/bundle/test_bundle_push_to_hf_hub.py,sha256=Zjl6xDwRKgkS6jvO5dzMBaTLEd4EXyMXp0_wzDNSY3g,1740
513
514
  tests/bundle/test_bundle_trt_export.py,sha256=png-2SGjBSt46LXSz-PLprOXwJ0WkC_3YLR3Ibk_WBc,6344
@@ -596,6 +597,7 @@ tests/integration/test_integration_determinism.py,sha256=AiSBXHcPwDtKRbt_lejI-ID
596
597
  tests/integration/test_integration_fast_train.py,sha256=WxEIJV52F0Cf2wmGlIQDiVs1m2QZrvxmta_UAsa0OCI,9736
597
598
  tests/integration/test_integration_gpu_customization.py,sha256=z-w6iBaY72LEi8TBVxZuzvsEBgBecZAP2YPwl6KFUhA,5547
598
599
  tests/integration/test_integration_lazy_samples.py,sha256=d_4GNy_ixiizvehIYJBht4dQropRsqQy7rJOpW7OkZ8,9198
600
+ tests/integration/test_integration_nnunet_bundle.py,sha256=V1X57m7cJwFsR5YfgzFLtCRe8vWx_wP5b2OZkb3Ux9Y,6813
599
601
  tests/integration/test_integration_nnunetv2_runner.py,sha256=KgyAI0Irl93KDLZyo8fGZjEL8dS5UXPKQz_osRfhtSU,4332
600
602
  tests/integration/test_integration_segmentation_3d.py,sha256=TSV8tdiloK4_E03DgM1SqJxMo4fcH-Ta1NutG-3cPFc,13229
601
603
  tests/integration/test_integration_sliding_window.py,sha256=N0CYquebXk8N3KiPcGWbD9KAf5UHuXx2pqAZY5PQVSE,3769
@@ -785,7 +787,7 @@ tests/networks/nets/test_spade_diffusion_model_unet.py,sha256=LEN1PAGid0DMdP2NyS
785
787
  tests/networks/nets/test_spade_vaegan.py,sha256=ur1SPoXEmpr_8KwVS6-E_1tIPMBKpNqsvHJ7z5-obzA,5632
786
788
  tests/networks/nets/test_swin_unetr.py,sha256=gj1Jqg8xTBYdCZWCR4Y9_ZlGNNYVTkCPmB2sdF2xIDM,5690
787
789
  tests/networks/nets/test_torchvision_fc_model.py,sha256=oNb-PaOhIAjOrpnsXApC2hKSUK6lMutIEinMrCOKQoA,6397
788
- tests/networks/nets/test_transchex.py,sha256=vUUsCd_CJrW_q0jcaGQegBoanJQVoufrs_EP3MC46Xo,3220
790
+ tests/networks/nets/test_transchex.py,sha256=G8WHEAlZlovlpJjlWD5cfeGD6FTFzUM6Y7_bVehHNY0,3293
789
791
  tests/networks/nets/test_transformer.py,sha256=rsGjemv0JV9SMTTWiZ8Sz_w5t5Rkz15b2rjJit4R2XA,4218
790
792
  tests/networks/nets/test_unet.py,sha256=wXwaXkufYDjFXzQ-AygbePAwigZLLaY58sGygizF3Q4,5801
791
793
  tests/networks/nets/test_unetr.py,sha256=3_V4VWfsQVB22-T8XTSRra3Her2XrLx5gzIRHis2zPs,5325
@@ -904,10 +906,7 @@ tests/transforms/test_histogram_normalized.py,sha256=dwaZ9ux-sgYKx0cy6aQqt5L07ts
904
906
  tests/transforms/test_image_filter.py,sha256=ERomnuZRJkdFL7wAObos22qxry2jpPCtT2QXML6hIWY,11619
905
907
  tests/transforms/test_intensity_stats.py,sha256=MjWFd_Oeu0Ay-rd9Asp2ZLiwg75u4SFmHvj-VwBGiHA,2795
906
908
  tests/transforms/test_intensity_statsd.py,sha256=tLuq1EQ6aVjGP_0xCCRVDZ1kPvtaqBuRwWy-EuxMhmQ,3595
907
- tests/transforms/test_inverse.py,sha256=vCj7yrm1L15HBEUEUdUgkXbfPckCnvslIltHncee7dk,18982
908
909
  tests/transforms/test_inverse_collation.py,sha256=8iptVqniLP77pfVJnLpE13xcthO-BgXoZCza8sGPAcA,5451
909
- tests/transforms/test_invert.py,sha256=gBJgAaVs4WKTkaYS8JNXH3qeKM8DBAZvF_t3GoPmVPU,4292
910
- tests/transforms/test_invertd.py,sha256=J7e_unCTiD1fXzAXLvCCKkVCGqNMJcIPentoOjmwxq4,6094
911
910
  tests/transforms/test_k_space_spike_noise.py,sha256=9jP6fFggTKScbR8orjJacSYtzwv1gQMuomPiaz1o1_0,2863
912
911
  tests/transforms/test_k_space_spike_noised.py,sha256=_n7b-0S6N5HEJBTLYQVKka8bpKZ2eL1xqOMUqB1cSi0,3511
913
912
  tests/transforms/test_keep_largest_connected_component.py,sha256=yXLKF3FdaVN5FFLq0okNunlQc0OI6CrAOhzIM9Gjcg4,14759
@@ -1105,8 +1104,12 @@ tests/transforms/intensity/test_rand_histogram_shiftd.py,sha256=0TFQO5qz5GVFyH95
1105
1104
  tests/transforms/intensity/test_scale_intensity_range_percentiles.py,sha256=y5O_BLLVxDqUmF3BvqNHgt5dg04FrwSK9qHEXI8IzXY,3986
1106
1105
  tests/transforms/intensity/test_scale_intensity_range_percentilesd.py,sha256=ZHSiTTJn5Lp1OaJVff7eq94OAHCc7gJZLSsTSuNFAhM,3980
1107
1106
  tests/transforms/inverse/__init__.py,sha256=s9djSd6kvViPnFvMR11Dgd30Lv4oY6FaPJr4ZZJZLq0,573
1107
+ tests/transforms/inverse/test_inverse.py,sha256=vCj7yrm1L15HBEUEUdUgkXbfPckCnvslIltHncee7dk,18982
1108
1108
  tests/transforms/inverse/test_inverse_array.py,sha256=KIFCHhkQSbVbirheLk4c9Kz0Uqpf9m5Do4LkD026ISk,2769
1109
- tests/transforms/inverse/test_traceable_transform.py,sha256=njTHREPWZvGV6mW550fXT8QJlIbGj6hAhNnPGsOruuU,1887
1109
+ tests/transforms/inverse/test_inverse_dict.py,sha256=Sd84lHWCr-IpWp8DUNspfSfRyfooBNa301hOS6pKJNE,4817
1110
+ tests/transforms/inverse/test_invert.py,sha256=gBJgAaVs4WKTkaYS8JNXH3qeKM8DBAZvF_t3GoPmVPU,4292
1111
+ tests/transforms/inverse/test_invertd.py,sha256=J7e_unCTiD1fXzAXLvCCKkVCGqNMJcIPentoOjmwxq4,6094
1112
+ tests/transforms/inverse/test_traceable_transform.py,sha256=1NEw_C755p_3Hr96qFYAYqSZQk1sRfuWiOK8N9z8hDs,1887
1110
1113
  tests/transforms/post/__init__.py,sha256=s9djSd6kvViPnFvMR11Dgd30Lv4oY6FaPJr4ZZJZLq0,573
1111
1114
  tests/transforms/post/test_label_filterd.py,sha256=OMIoSlbTu8owWE2WqcRfobUDRZE96mpLaE1fuWpdWdY,2597
1112
1115
  tests/transforms/post/test_probnms.py,sha256=-HMnXkVLqXiMkvgJeD7jDoLkm74gNwE57iigi63waKo,2866
@@ -1186,7 +1189,7 @@ tests/visualize/test_vis_gradcam.py,sha256=WpA-pvTB75eZs7JoIc5qyvOV9PwgkzWI8-Vow
1186
1189
  tests/visualize/utils/__init__.py,sha256=s9djSd6kvViPnFvMR11Dgd30Lv4oY6FaPJr4ZZJZLq0,573
1187
1190
  tests/visualize/utils/test_blend_images.py,sha256=RVs2p_8RWQDfhLHDNNtZaMig27v8o0km7XxNa-zWjKE,2274
1188
1191
  tests/visualize/utils/test_matshow3d.py,sha256=wXYj77L5Jvnp0f6DvL1rsi_-YlCxS0HJ9hiPmrbpuP8,5021
1189
- monai_weekly-1.5.dev2513.dist-info/METADATA,sha256=JtMbpoy1PATNUbzheFGRBPWYUP9Ka18xyiyNHGhad8k,12008
1190
- monai_weekly-1.5.dev2513.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
1191
- monai_weekly-1.5.dev2513.dist-info/top_level.txt,sha256=hn2Y6P9xBf2R8faMeVMHhPMvrdDKxMsIOwMDYI0yTjs,12
1192
- monai_weekly-1.5.dev2513.dist-info/RECORD,,
1192
+ monai_weekly-1.5.dev2515.dist-info/METADATA,sha256=0PRAJeakVM2LmWoAgV6ooMkk8Z-btuFbcstMou9dQaA,12104
1193
+ monai_weekly-1.5.dev2515.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
1194
+ monai_weekly-1.5.dev2515.dist-info/top_level.txt,sha256=hn2Y6P9xBf2R8faMeVMHhPMvrdDKxMsIOwMDYI0yTjs,12
1195
+ monai_weekly-1.5.dev2515.dist-info/RECORD,,
@@ -63,6 +63,8 @@ TEST_CASE_5 = [
63
63
 
64
64
  TEST_CASE_6 = [["models/model.pt", "configs/train.json"], "renalStructures_CECT_segmentation", "0.1.0"]
65
65
 
66
+ TEST_CASE_6_HF = [["models/model.pt", "configs/train.yaml"], "mednist_ddpm", "1.0.1"]
67
+
66
68
  TEST_CASE_7 = [
67
69
  ["model.pt", "model.ts", "network.json", "test_output.pt", "test_input.pt"],
68
70
  "test_bundle",
@@ -193,6 +195,7 @@ class TestDownload(unittest.TestCase):
193
195
 
194
196
  @parameterized.expand([TEST_CASE_6])
195
197
  @skip_if_quick
198
+ @skipUnless(has_huggingface_hub, "Requires `huggingface_hub`.")
196
199
  def test_monaihosting_source_download_bundle(self, bundle_files, bundle_name, version):
197
200
  with skip_if_downloading_fails():
198
201
  # download a single file from url, also use `args_file`
@@ -239,6 +242,7 @@ class TestDownload(unittest.TestCase):
239
242
  self.assertEqual(_list_latest_versions(data), ["1.1", "1.0"])
240
243
 
241
244
  @skip_if_quick
245
+ @skipUnless(has_huggingface_hub, "Requires `huggingface_hub`.")
242
246
  @patch("monai.bundle.scripts.get_versions", return_value={"version": "1.2"})
243
247
  def test_download_monaihosting(self, mock_get_versions):
244
248
  """Test checking MONAI version from a metadata file."""
@@ -333,6 +337,7 @@ class TestLoad(unittest.TestCase):
333
337
 
334
338
  @parameterized.expand([TEST_CASE_8])
335
339
  @skip_if_quick
340
+ @skipUnless(has_huggingface_hub, "Requires `huggingface_hub`.")
336
341
  def test_load_weights_with_net_override(self, bundle_name, device, net_override):
337
342
  with skip_if_downloading_fails():
338
343
  # download bundle, and load weights from the downloaded path
@@ -0,0 +1,150 @@
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 __future__ import annotations
13
+
14
+ import os
15
+ import tempfile
16
+ import unittest
17
+ from pathlib import Path
18
+
19
+ import numpy as np
20
+
21
+ from monai.apps.nnunet import nnUNetV2Runner
22
+ from monai.apps.nnunet.nnunet_bundle import (
23
+ convert_nnunet_to_monai_bundle,
24
+ get_nnunet_monai_predictor,
25
+ get_nnunet_trainer,
26
+ )
27
+ from monai.bundle.config_parser import ConfigParser
28
+ from monai.data import DataLoader, Dataset, create_test_image_3d
29
+ from monai.transforms import Compose, Decollated, EnsureChannelFirstd, LoadImaged, SaveImaged
30
+ from monai.utils import optional_import
31
+ from tests.test_utils import SkipIfBeforePyTorchVersion, skip_if_downloading_fails, skip_if_no_cuda, skip_if_quick
32
+
33
+ _, has_tb = optional_import("torch.utils.tensorboard", name="SummaryWriter")
34
+ _, has_nnunet = optional_import("nnunetv2")
35
+
36
+ sim_datalist: dict[str, list[dict]] = {
37
+ "testing": [{"image": "val_001.fake.nii.gz"}, {"image": "val_002.fake.nii.gz"}],
38
+ "training": [
39
+ {"fold": 0, "image": "tr_image_001.fake.nii.gz", "label": "tr_label_001.fake.nii.gz"},
40
+ {"fold": 0, "image": "tr_image_002.fake.nii.gz", "label": "tr_label_002.fake.nii.gz"},
41
+ {"fold": 1, "image": "tr_image_003.fake.nii.gz", "label": "tr_label_003.fake.nii.gz"},
42
+ {"fold": 1, "image": "tr_image_004.fake.nii.gz", "label": "tr_label_004.fake.nii.gz"},
43
+ {"fold": 2, "image": "tr_image_005.fake.nii.gz", "label": "tr_label_005.fake.nii.gz"},
44
+ {"fold": 2, "image": "tr_image_006.fake.nii.gz", "label": "tr_label_006.fake.nii.gz"},
45
+ {"fold": 3, "image": "tr_image_007.fake.nii.gz", "label": "tr_label_007.fake.nii.gz"},
46
+ {"fold": 3, "image": "tr_image_008.fake.nii.gz", "label": "tr_label_008.fake.nii.gz"},
47
+ {"fold": 4, "image": "tr_image_009.fake.nii.gz", "label": "tr_label_009.fake.nii.gz"},
48
+ {"fold": 4, "image": "tr_image_010.fake.nii.gz", "label": "tr_label_010.fake.nii.gz"},
49
+ ],
50
+ }
51
+
52
+
53
+ @skip_if_quick
54
+ @SkipIfBeforePyTorchVersion((1, 13, 0))
55
+ @unittest.skipIf(not has_tb, "no tensorboard summary writer")
56
+ @unittest.skipIf(not has_nnunet, "no nnunetv2")
57
+ class TestnnUNetBundle(unittest.TestCase):
58
+
59
+ def setUp(self) -> None:
60
+
61
+ import nibabel as nib
62
+
63
+ self.test_dir = tempfile.TemporaryDirectory()
64
+ test_path = self.test_dir.name
65
+
66
+ sim_dataroot = os.path.join(test_path, "dataroot")
67
+ if not os.path.isdir(sim_dataroot):
68
+ os.makedirs(sim_dataroot)
69
+
70
+ self.sim_dataroot = sim_dataroot
71
+ # Generate a fake dataset
72
+ for d in sim_datalist["testing"] + sim_datalist["training"]:
73
+ im, seg = create_test_image_3d(24, 24, 24, rad_max=10, num_seg_classes=2)
74
+ nib_image = nib.Nifti1Image(im, affine=np.eye(4))
75
+ image_fpath = os.path.join(sim_dataroot, d["image"])
76
+ nib.save(nib_image, image_fpath)
77
+
78
+ if "label" in d:
79
+ nib_image = nib.Nifti1Image(seg, affine=np.eye(4))
80
+ label_fpath = os.path.join(sim_dataroot, d["label"])
81
+ nib.save(nib_image, label_fpath)
82
+
83
+ sim_json_datalist = os.path.join(sim_dataroot, "sim_input.json")
84
+ ConfigParser.export_config_file(sim_datalist, sim_json_datalist)
85
+
86
+ data_src_cfg = os.path.join(test_path, "data_src_cfg.yaml")
87
+ data_src = {"modality": "CT", "datalist": sim_json_datalist, "dataroot": sim_dataroot}
88
+
89
+ ConfigParser.export_config_file(data_src, data_src_cfg)
90
+ self.data_src_cfg = data_src_cfg
91
+ self.test_path = test_path
92
+
93
+ @skip_if_no_cuda
94
+ def test_nnunet_bundle(self) -> None:
95
+ runner = nnUNetV2Runner(
96
+ input_config=self.data_src_cfg, trainer_class_name="nnUNetTrainer_1epoch", work_dir=self.test_path
97
+ )
98
+ with skip_if_downloading_fails():
99
+ runner.run(run_train=False, run_find_best_configuration=False, run_predict_ensemble_postprocessing=False)
100
+
101
+ nnunet_trainer = get_nnunet_trainer(
102
+ dataset_name_or_id=runner.dataset_name, fold=0, configuration="3d_fullres"
103
+ )
104
+
105
+ print("Max Epochs: ", nnunet_trainer.num_epochs)
106
+ print("Num Iterations: ", nnunet_trainer.num_iterations_per_epoch)
107
+ print("Train Batch dims: ", next(nnunet_trainer.dataloader_train.generator)["data"].shape)
108
+ print("Val Batch dims: ", next(nnunet_trainer.dataloader_val.generator)["data"].shape)
109
+ print("Network: ", nnunet_trainer.network)
110
+ print("Optimizer: ", nnunet_trainer.optimizer)
111
+ print("Loss Function: ", nnunet_trainer.loss)
112
+ print("LR Scheduler: ", nnunet_trainer.lr_scheduler)
113
+ print("Device: ", nnunet_trainer.device)
114
+ runner.train_single_model("3d_fullres", fold=0)
115
+
116
+ nnunet_config = {"dataset_name_or_id": "001", "nnunet_trainer": "nnUNetTrainer_1epoch"}
117
+ self.bundle_root = os.path.join("bundle_root")
118
+
119
+ Path(self.bundle_root).joinpath("models").mkdir(parents=True, exist_ok=True)
120
+ convert_nnunet_to_monai_bundle(nnunet_config, self.bundle_root, 0)
121
+
122
+ data_transforms = Compose([LoadImaged(keys="image"), EnsureChannelFirstd(keys="image")])
123
+ dataset = Dataset(
124
+ data=[{"image": os.path.join(self.test_path, "dataroot", "val_001.fake.nii.gz")}], transform=data_transforms
125
+ )
126
+ data_loader = DataLoader(dataset, batch_size=1)
127
+ input = next(iter(data_loader))
128
+
129
+ predictor = get_nnunet_monai_predictor(Path(self.bundle_root).joinpath("models", "fold_0"))
130
+ pred_batch = predictor(input["image"])
131
+ Path(self.sim_dataroot).joinpath("predictions").mkdir(parents=True, exist_ok=True)
132
+
133
+ post_processing_transforms = Compose(
134
+ [
135
+ Decollated(keys=None, detach=True),
136
+ # Not needed after reading the data directly from the MONAI LoadImaged Transform
137
+ # Transposed(keys="pred", indices=[0, 3, 2, 1]),
138
+ SaveImaged(
139
+ keys="pred", output_dir=Path(self.sim_dataroot).joinpath("predictions"), output_postfix="pred"
140
+ ),
141
+ ]
142
+ )
143
+ post_processing_transforms({"pred": pred_batch})
144
+
145
+ def tearDown(self) -> None:
146
+ self.test_dir.cleanup()
147
+
148
+
149
+ if __name__ == "__main__":
150
+ unittest.main()
@@ -18,7 +18,7 @@ from parameterized import parameterized
18
18
 
19
19
  from monai.networks import eval_mode
20
20
  from monai.networks.nets.transchex import Transchex
21
- from tests.test_utils import skip_if_quick
21
+ from tests.test_utils import skip_if_downloading_fails, skip_if_quick
22
22
 
23
23
  TEST_CASE_TRANSCHEX = []
24
24
  for drop_out in [0.4]:
@@ -49,7 +49,8 @@ for drop_out in [0.4]:
49
49
  class TestTranschex(unittest.TestCase):
50
50
  @parameterized.expand(TEST_CASE_TRANSCHEX)
51
51
  def test_shape(self, input_param, expected_shape):
52
- net = Transchex(**input_param)
52
+ with skip_if_downloading_fails():
53
+ net = Transchex(**input_param)
53
54
  with eval_mode(net):
54
55
  result = net(torch.randint(2, (2, 512)), torch.randint(2, (2, 512)), torch.randn((2, 3, 224, 224)))
55
56
  self.assertEqual(result.shape, expected_shape)