Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
2 changes: 1 addition & 1 deletion .github/workflows/pythonapp-min.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pytorch-version: ['2.4.1', '2.5.1', '2.6.0', '2.7.1']
pytorch-version: ['2.5.1', '2.6.0', '2.7.1', '2.8.0']
timeout-minutes: 40
steps:
- uses: actions/checkout@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
- if: runner.os == 'windows'
name: Install torch cpu from pytorch.org (Windows only)
run: |
python -m pip install torch==2.4.1 torchvision==0.19.1+cpu --index-url https://download.pytorch.org/whl/cpu
python -m pip install torch==2.5.1 torchvision==0.20.1+cpu --index-url https://download.pytorch.org/whl/cpu
- if: runner.os == 'Linux'
name: Install itk pre-release (Linux only)
run: |
Expand All @@ -103,7 +103,7 @@ jobs:
- name: Install the dependencies
run: |
python -m pip install --user --upgrade pip wheel
python -m pip install torch==2.4.1 torchvision==0.19.1
python -m pip install torch==2.5.1 torchvision==0.20.1
cat "requirements-dev.txt"
python -m pip install -r requirements-dev.txt
python -m pip list
Expand Down Expand Up @@ -155,7 +155,7 @@ jobs:
# install the latest pytorch for testing
# however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated
# fresh torch installation according to pyproject.toml
python -m pip install torch>=2.4.1 torchvision
python -m pip install torch>=2.5.1 torchvision
- name: Check packages
run: |
pip uninstall monai
Expand Down
5 changes: 2 additions & 3 deletions monai/apps/detection/metrics/coco.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ def _compute_statistics(self, results_list: list[dict[int, dict[str, np.ndarray]
dt_ignores = np.concatenate([r["dtIgnore"][:, 0:max_det] for r in results], axis=1)[:, inds]
self.check_number_of_iou(dt_matches, dt_ignores)
gt_ignore = np.concatenate([r["gtIgnore"] for r in results])
num_gt = np.count_nonzero(gt_ignore == 0) # number of ground truth boxes (non ignored)
num_gt = int(np.count_nonzero(gt_ignore == 0)) # number of ground truth boxes (non ignored)
if num_gt == 0:
logger.warning(f"WARNING, no gt found for coco metric for class {cls_i}")
continue
Expand Down Expand Up @@ -523,13 +523,12 @@ def _compute_stats_single_threshold(
recall = 0

# array where precision values nearest to given recall th are saved
precision = np.zeros((num_recall_th,))
precision = [0.0] * num_recall_th
# save scores for corresponding recall value in here
th_scores = np.zeros((num_recall_th,))
# numpy is slow without cython optimization for accessing elements
# use python array gets significant speed improvement
pr = pr.tolist()
precision = precision.tolist()

# smooth precision curve (create box shape)
for i in range(len(tp) - 1, 0, -1):
Expand Down
5 changes: 4 additions & 1 deletion monai/apps/detection/utils/box_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,10 @@ def decode_single(self, rel_codes: Tensor, reference_boxes: Tensor) -> Tensor:
offset = reference_boxes.shape[-1]

pred_boxes = []
boxes_cccwhd = convert_box_mode(reference_boxes, src_mode=StandardMode, dst_mode=CenterSizeMode)
boxes_cccwhd: torch.Tensor = convert_box_mode(
reference_boxes, src_mode=StandardMode, dst_mode=CenterSizeMode
) # type: ignore[assignment]

for axis in range(self.spatial_dims):
whd_axis = boxes_cccwhd[:, axis + self.spatial_dims]
ctr_xyz_axis = boxes_cccwhd[:, axis]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,9 @@ def _apply_down_blocks(self, h, emb, context, down_block_additional_residuals):

def _apply_up_blocks(self, h, emb, context, down_block_res_samples):
for upsample_block in self.up_blocks:
res_samples = down_block_res_samples[-len(upsample_block.resnets) :]
down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)]
idx: int = -len(upsample_block.resnets) # type: ignore
res_samples = down_block_res_samples[idx:]
down_block_res_samples = down_block_res_samples[:idx]
h = upsample_block(hidden_states=h, res_hidden_states_list=res_samples, temb=emb, context=context)

return h
Expand Down
6 changes: 3 additions & 3 deletions monai/data/box_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -811,9 +811,9 @@ def _box_inter_union(

# compute size for the intersection region for the NxM combinations
wh = (rb - lt + TO_REMOVE).clamp(min=0) # (N,M,spatial_dims)
inter = torch.prod(wh, dim=-1, keepdim=False) # (N,M)
inter: torch.Tensor = torch.prod(wh, dim=-1, keepdim=False) # (N,M)

union = area1[:, None] + area2 - inter
union: torch.Tensor = area1[:, None] + area2 - inter # type: ignore
return inter, union


Expand Down Expand Up @@ -981,7 +981,7 @@ def box_pair_giou(boxes1: NdarrayOrTensor, boxes2: NdarrayOrTensor) -> NdarrayOr
wh = (rb - lt + TO_REMOVE).clamp(min=0) # (N,spatial_dims)
enclosure = torch.prod(wh, dim=-1, keepdim=False) # (N,)

giou_t = iou - (enclosure - union) / (enclosure + torch.finfo(COMPUTE_DTYPE).eps)
giou_t: torch.Tensor = iou - (enclosure - union) / (enclosure + torch.finfo(COMPUTE_DTYPE).eps) # type: ignore
giou_t = giou_t.to(dtype=box_dtype) # (N,spatial_dims)
if torch.isnan(giou_t).any() or torch.isinf(giou_t).any():
raise ValueError("Box GIoU is NaN or Inf.")
Expand Down
2 changes: 1 addition & 1 deletion monai/data/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ def __len__(self) -> int:
return len(self.dataset)

def randomize(self, data: Any | None = None) -> None:
self._seed = self.R.randint(MAX_SEED, dtype="uint32")
self._seed = int(self.R.randint(MAX_SEED, dtype="uint32"))

def __getitem__(self, index: int):
self.randomize()
Expand Down
2 changes: 1 addition & 1 deletion monai/data/image_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def __len__(self) -> int:
return len(self.image_files)

def randomize(self, data: Any | None = None) -> None:
self._seed = self.R.randint(MAX_SEED, dtype="uint32")
self._seed = int(self.R.randint(MAX_SEED, dtype="uint32"))

def __getitem__(self, index: int):
self.randomize()
Expand Down
12 changes: 7 additions & 5 deletions monai/data/image_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ def _combine_dicom_series(self, data: Iterable, filenames: Sequence[PathLike]):
shape = first_array.shape
spacing = getattr(first_slice, "PixelSpacing", [1.0] * len(shape))
prev_pos = getattr(first_slice, "ImagePositionPatient", (0.0, 0.0, 0.0))[2]
stack_array = [first_array]
stack_array_list: list = [first_array]
for idx in range(1, len(slices)):
slc_array = self._get_array_data(slices[idx][0], slices[idx][1])
slc_shape = slc_array.shape
Expand All @@ -592,22 +592,24 @@ def _combine_dicom_series(self, data: Iterable, filenames: Sequence[PathLike]):
warnings.warn(f"the list contains slices that have different shapes {shape} and {slc_shape}.")
average_distance += abs(prev_pos - slc_pos)
prev_pos = slc_pos
stack_array.append(slc_array)
stack_array_list.append(slc_array)

if len(slices) > 1:
average_distance /= len(slices) - 1
spacing.append(average_distance)
if self.to_gpu:
stack_array = cp.stack(stack_array, axis=-1)
stack_array = cp.stack(stack_array_list, axis=-1)
else:
stack_array = np.stack(stack_array, axis=-1)
stack_array = np.stack(stack_array_list, axis=-1)

del stack_array_list[:]
stack_metadata = self._get_meta_dict(first_slice)
stack_metadata["spacing"] = np.asarray(spacing)
if hasattr(slices[-1][0], "ImagePositionPatient"):
stack_metadata["lastImagePositionPatient"] = np.asarray(slices[-1][0].ImagePositionPatient)
stack_metadata[MetaKeys.SPATIAL_SHAPE] = shape + (len(slices),)
else:
stack_array = stack_array[0]
stack_array = stack_array_list[0]
stack_metadata = self._get_meta_dict(first_slice)
stack_metadata["spacing"] = np.asarray(spacing)
stack_metadata[MetaKeys.SPATIAL_SHAPE] = shape
Expand Down
5 changes: 3 additions & 2 deletions monai/networks/nets/diffusion_model_unet.py
Original file line number Diff line number Diff line change
Expand Up @@ -1795,8 +1795,9 @@ def forward(

# 6. up
for upsample_block in self.up_blocks:
res_samples = down_block_res_samples[-len(upsample_block.resnets) :]
down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)]
idx: int = -len(upsample_block.resnets) # type: ignore
res_samples = down_block_res_samples[idx:]
down_block_res_samples = down_block_res_samples[:idx]
h = upsample_block(hidden_states=h, res_hidden_states_list=res_samples, temb=emb, context=context)

# 7. output block
Expand Down
14 changes: 6 additions & 8 deletions monai/networks/nets/dints.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ def forward(self, x: torch.Tensor):
inputs = []
for d in range(self.num_depths):
# allow multi-resolution input
_mod_w: StemInterface = self.stem_down[str(d)]
_mod_w: StemInterface = self.stem_down[str(d)] # type: ignore[assignment]
x_out = _mod_w.forward(x)
if self.node_a[0][d]:
inputs.append(x_out)
Expand All @@ -505,7 +505,7 @@ def forward(self, x: torch.Tensor):
start = False
_temp: torch.Tensor = torch.empty(0)
for res_idx in range(self.num_depths - 1, -1, -1):
_mod_up: StemInterface = self.stem_up[str(res_idx)]
_mod_up: StemInterface = self.stem_up[str(res_idx)] # type: ignore[assignment]
if start:
_temp = _mod_up.forward(outputs[res_idx] + _temp)
elif self.node_a[blk_idx + 1][res_idx]:
Expand Down Expand Up @@ -680,7 +680,7 @@ def forward(self, x: list[torch.Tensor]) -> list[torch.Tensor]:
outputs = [torch.tensor(0.0, dtype=x[0].dtype, device=x[0].device)] * self.num_depths
for res_idx, activation in enumerate(self.arch_code_a[blk_idx].data):
if activation:
mod: CellInterface = self.cell_tree[str((blk_idx, res_idx))]
mod: CellInterface = self.cell_tree[str((blk_idx, res_idx))] # type: ignore[assignment]
_out = mod.forward(x=inputs[self.arch_code2in[res_idx]], weight=None)
outputs[self.arch_code2out[res_idx]] = outputs[self.arch_code2out[res_idx]] + _out
inputs = outputs
Expand Down Expand Up @@ -782,12 +782,10 @@ def __init__(
for blk_idx in range(self.num_blocks):
for res_idx in range(len(self.arch_code2out)):
if self.arch_code_a[blk_idx, res_idx] == 1:
cell_inter: Cell = self.cell_tree[str((blk_idx, res_idx))] # type: ignore
self.ram_cost[blk_idx, res_idx] = np.array(
[
op.ram_cost + self.cell_tree[str((blk_idx, res_idx))].preprocess.ram_cost
for op in self.cell_tree[str((blk_idx, res_idx))].op.ops[: self.num_cell_ops]
]
)
[op.ram_cost + cell_inter.preprocess.ram_cost for op in cell_inter.op.ops[: self.num_cell_ops]]
) # type: ignore

# define cell and macro architecture probabilities
self.log_alpha_c = nn.Parameter(
Expand Down
6 changes: 4 additions & 2 deletions monai/networks/nets/efficientnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,10 @@ def set_swish(self, memory_efficient: bool = True) -> None:

"""
self._swish = Act["memswish"]() if memory_efficient else Act["swish"](alpha=1.0)
for sub_stack in self._blocks:
for block in sub_stack:
sub_stack: nn.Sequential
block: MBConvBlock
for sub_stack in self._blocks: # type: ignore[assignment]
for block in sub_stack: # type: ignore[assignment]
block.set_swish(memory_efficient)

def forward(self, inputs: torch.Tensor):
Expand Down
11 changes: 7 additions & 4 deletions monai/networks/nets/segresnet_ds.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ def _forward(self, x: torch.Tensor) -> list[torch.Tensor]:
outputs = []
x = self.conv_init(x)

for level in self.layers:
level: nn.ModuleDict
for level in self.layers: # type: ignore[assignment]
x = level["blocks"](x)
outputs.append(x)
x = level["downsample"](x)
Expand Down Expand Up @@ -406,7 +407,8 @@ def _forward(self, x: torch.Tensor) -> Union[None, torch.Tensor, list[torch.Tens
outputs: list[torch.Tensor] = []

i = 0
for level in self.up_layers:
level: nn.ModuleDict
for level in self.up_layers: # type: ignore
x = level["upsample"](x)
x += x_down.pop(0)
x = level["blocks"](x)
Expand Down Expand Up @@ -508,12 +510,13 @@ def forward( # type: ignore

outputs: list[torch.Tensor] = []
outputs_auto: list[torch.Tensor] = []
level: nn.ModuleDict
x_ = x
if with_point:
if with_label:
x_ = x.clone()
i = 0
for level in self.up_layers:
for level in self.up_layers: # type: ignore
x = level["upsample"](x)
x = x + x_down[i]
x = level["blocks"](x)
Expand All @@ -526,7 +529,7 @@ def forward( # type: ignore
x = x_
if with_label:
i = 0
for level in self.up_layers_auto:
for level in self.up_layers_auto: # type: ignore
x = level["upsample"](x)
x = x + x_down[i]
x = level["blocks"](x)
Expand Down
5 changes: 3 additions & 2 deletions monai/networks/nets/spade_diffusion_model_unet.py
Original file line number Diff line number Diff line change
Expand Up @@ -961,8 +961,9 @@ def forward(

# 6. up
for upsample_block in self.up_blocks:
res_samples = down_block_res_samples[-len(upsample_block.resnets) :]
down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)]
idx: int = -len(upsample_block.resnets) # type: ignore
res_samples = down_block_res_samples[idx:]
down_block_res_samples = down_block_res_samples[:idx]
h = upsample_block(hidden_states=h, res_hidden_states_list=res_samples, seg=seg, temb=emb, context=context)

# 7. output block
Expand Down
2 changes: 1 addition & 1 deletion monai/transforms/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def set_random_state(self, seed: int | None = None, state: np.random.RandomState
for _transform in self.transforms:
if not isinstance(_transform, Randomizable):
continue
_transform.set_random_state(seed=self.R.randint(MAX_SEED, dtype="uint32"))
_transform.set_random_state(seed=int(self.R.randint(MAX_SEED, dtype="uint32")))
return self

def randomize(self, data: Any | None = None) -> None:
Expand Down
2 changes: 1 addition & 1 deletion monai/transforms/croppad/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ def __call__(

lazy_ = self.lazy if lazy is None else lazy
for key in self.key_iterator(dict(data)):
self.cropper.set_random_state(seed=self.sub_seed)
self.cropper.set_random_state(seed=int(self.sub_seed))
for i, im in enumerate(self.cropper(data[key], lazy=lazy_)):
ret[i][key] = im
return ret
Expand Down
25 changes: 13 additions & 12 deletions monai/transforms/intensity/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -900,27 +900,28 @@ def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor:
"""
Apply the transform to `img`, assuming `img` is a channel-first array if `self.channel_wise` is True,
"""
img = convert_to_tensor(img, track_meta=get_track_meta())
img_t: torch.Tensor = convert_to_tensor(img, track_meta=get_track_meta()) # type: ignore[assignment]
dtype = self.dtype or img.dtype
img_len = len(img_t)
if self.channel_wise:
if self.subtrahend is not None and len(self.subtrahend) != len(img):
raise ValueError(f"img has {len(img)} channels, but subtrahend has {len(self.subtrahend)} components.")
if self.divisor is not None and len(self.divisor) != len(img):
raise ValueError(f"img has {len(img)} channels, but divisor has {len(self.divisor)} components.")
if self.subtrahend is not None and len(self.subtrahend) != img_len:
raise ValueError(f"img has {img_len} channels, but subtrahend has {len(self.subtrahend)} components.")
if self.divisor is not None and len(self.divisor) != img_len:
raise ValueError(f"img has {img_len} channels, but divisor has {len(self.divisor)} components.")

if not img.dtype.is_floating_point:
img, *_ = convert_data_type(img, dtype=torch.float32)
if not img_t.dtype.is_floating_point:
img_t, *_ = convert_data_type(img_t, dtype=torch.float32)

for i, d in enumerate(img):
img[i] = self._normalize( # type: ignore
for i, d in enumerate(img_t):
img_t[i] = self._normalize( # type: ignore
d,
sub=self.subtrahend[i] if self.subtrahend is not None else None,
div=self.divisor[i] if self.divisor is not None else None,
)
else:
img = self._normalize(img, self.subtrahend, self.divisor)
img_t = self._normalize(img_t, self.subtrahend, self.divisor) # type: ignore[assignment]

out = convert_to_dst_type(img, img, dtype=dtype)[0]
out = convert_to_dst_type(img_t, img, dtype=dtype)[0]
return out


Expand Down Expand Up @@ -2764,7 +2765,7 @@ def __init__(self, dtype: DtypeLike = "float32") -> None:
self.dtype = dtype

def __call__(self, mask: NdarrayOrTensor):
instance_mask = convert_data_type(mask, np.ndarray)[0]
instance_mask: np.ndarray = convert_data_type(mask, np.ndarray)[0] # type: ignore[assignment]

h_map = instance_mask.astype(self.dtype, copy=True)
v_map = instance_mask.astype(self.dtype, copy=True)
Expand Down
9 changes: 6 additions & 3 deletions monai/transforms/spatial/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,8 @@ def __call__(

"""
lazy_ = self.lazy if lazy is None else lazy
_device: torch.device | None

if not lazy_:
if grid is None: # create grid from spatial_size
if spatial_size is None:
Expand All @@ -1749,10 +1751,10 @@ def __call__(
grid_ = grid
_dtype = self.dtype or grid_.dtype
grid_: torch.Tensor = convert_to_tensor(grid_, dtype=_dtype, track_meta=get_track_meta()) # type: ignore
_device = grid_.device # type: ignore
_device = torch.device(grid_.device) # type: ignore
spatial_dims = len(grid_.shape) - 1
else:
_device = self.device
_device = self.device # type: ignore[assignment]
spatial_dims = len(spatial_size) # type: ignore
_b = TransformBackends.TORCH
affine: torch.Tensor
Expand Down Expand Up @@ -3309,6 +3311,7 @@ def __call__(self, array: NdarrayOrTensor) -> MetaTensor:
**self.pad_kwargs,
)
patches = list(zip(*patch_iterator))
patched_image: NdarrayOrTensor
patched_image = np.stack(patches[0]) if isinstance(array, np.ndarray) else torch.stack(patches[0])
locations = np.stack(patches[1])[:, 1:, 0] # only keep the starting location

Expand Down Expand Up @@ -3516,7 +3519,7 @@ def __call__(self, img: torch.Tensor, randomize: bool = True) -> torch.Tensor:

if self._do_transform:
input_shape = img.shape[1:]
target_shape = np.round(np.array(input_shape) * self.zoom_factor).astype(np.int_)
target_shape = tuple(np.round(np.array(input_shape) * self.zoom_factor).astype(np.int_).tolist())

resize_tfm_downsample = Resize(
spatial_size=target_shape, size_mode="all", mode=self.downsample_mode, anti_aliasing=False
Expand Down
2 changes: 1 addition & 1 deletion monai/transforms/utility/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -941,7 +941,7 @@ def __call__(
data = where(in1d(img, select_labels), True, False).reshape(img.shape)

if merge_channels or self.merge_channels:
return data.any(0)[None]
return data.any(0)[None] # type: ignore

return data

Expand Down
Loading
Loading