Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
13eb352
feat: add pyrefly alongside mypy; drop deprecated pytype
garciadias Jun 23, 2026
023516d
fix: suppress pre-existing pyrefly errors across monai codebase
garciadias Jun 23, 2026
c398f2a
fix: address PR #8868 review feedback (#8865)
garciadias Jun 26, 2026
769c33b
fix: restore spatial_ndim to MetaTensor, keep pyrefly tooling changes
garciadias Jun 26, 2026
dd68613
fix: restore mypy gitignore entries and Transposed doc note
garciadias Jun 26, 2026
989b50b
fix: restore setup.cfg mypy config comments to match upstream
garciadias Jun 26, 2026
5f19fa3
fix: narrow spatial_size type from Sized to Sequence[int]
garciadias Jun 26, 2026
4e586e4
autofix
garciadias Jun 26, 2026
10587c7
Merge branch 'dev' into 1760-replace-mypy-with-ty-type-checker
ericspod Jun 29, 2026
34c0bd5
fix: address PR #8868 review feedback (#8865)
garciadias Jul 7, 2026
3db780c
fix: remove mypy; suppress enum invalid-annotation globally (#8865)
garciadias Jul 8, 2026
d92631e
Merge remote-tracking branch 'upstream/dev' into 1760-replace-mypy-wi…
garciadias Jul 8, 2026
f88480f
fix: address remaining PR #8868 review feedback from ericspod
garciadias Aug 11, 2026
cac7cbf
Merge remote-tracking branch 'upstream/dev' into 1760-replace-mypy-wi…
garciadias Aug 11, 2026
cf547b8
fix: resolve pyrefly inconsistent-inheritance in DepthwiseFFTConv{2,3}d
garciadias Aug 11, 2026
26dd16c
revert setup.cfg to upstream: keep mypy configuration sections
garciadias Aug 13, 2026
ca29978
restore [tool.pytype] configuration removed alongside the pytype runner
garciadias Aug 13, 2026
1502aa3
suppress unnecessary-type-conversion in pyrefly config instead of 75 …
garciadias Aug 13, 2026
85d91d0
Merge branch 'dev' into 1760-replace-mypy-with-ty-type-checker
garciadias Aug 14, 2026
a183cfe
Merge remote-tracking branch 'origin/1760-replace-mypy-with-ty-type-c…
garciadias Aug 14, 2026
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
5 changes: 2 additions & 3 deletions .github/workflows/cicd_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
opt: ["codeformat", "mypy"] # "pytype" omitted for being essentially deprecated, see #8865
opt: ["codeformat", "pyrefly"]
steps:
- name: Clean unused tools
run: |
Expand All @@ -80,8 +80,7 @@ jobs:
run: |
# clean up temporary files
$(pwd)/runtests.sh --build --clean
# Github actions have multiple cores, so parallelize pytype
$(pwd)/runtests.sh --build --${{ matrix.opt }} -j $(nproc --all)
$(pwd)/runtests.sh --build --${{ matrix.opt }}

min-dep: # Test with minumum dependencies installed for different OS, Python, and PyTorch combinations
runs-on: ${{ matrix.os }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ jobs:
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")))'
ngc --version
BUILD_MONAI=1 ./runtests.sh --build --coverage --unittests --disttests # unit tests with pytype checks, coverage report
BUILD_MONAI=1 ./runtests.sh --build --coverage --pyrefly --unittests --disttests # unit tests with pyrefly checks, coverage report
BUILD_MONAI=1 ./runtests.sh --build --coverage --net # integration tests with coverage report
coverage xml --ignore-errors
if pgrep python; then pkill python; fi
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/weekly-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
opt: ["codeformat", "mypy"]
opt: ["codeformat", "pyrefly"]
steps:
- name: Clean unused tools
run: |
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,17 @@ venv.bak/
# pytype cache
Comment thread
ericspod marked this conversation as resolved.
.pytype/

# pyrefly cache
.pyrefly_cache/

# mypy
.mypy_cache/
Comment thread
garciadias marked this conversation as resolved.
.dmypy.json

examples/scd_lvsegs.npz
temp/
.idea/
.dmypy.json
.plans/

*~

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Please note that, as per PyTorch, MONAI uses American English spelling. This mea
### Preparing pull requests

To ensure the code quality, MONAI relies on several linting tools ([black](https://github.com/psf/black), [isort](https://github.com/timothycrosley/isort), [ruff](https://github.com/astral-sh/ruff)),
static type analysis tools ([mypy](https://github.com/python/mypy), [pytype](https://github.com/google/pytype)), as well as a set of unit/integration tests.
static type analysis tools ([pyrefly](https://github.com/facebook/pyrefly)), as well as a set of unit/integration tests.

This section highlights all the necessary preparation steps required before sending a pull request.
To collaborate efficiently, please read through this section and follow them.
Expand Down
2 changes: 2 additions & 0 deletions monai/apps/auto3dseg/auto_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ def _train_algo_in_nni(self, history: list[dict[str, Any]]) -> None:
nni_config_filename = os.path.abspath(os.path.join(self.work_dir, f"{name}_nni_config.yaml"))
ConfigParser.export_config_file(nni_config, nni_config_filename, fmt="yaml", default_flow_style=None)

# pyrefly: ignore [redundant-cast]
max_trial = min(self.hpo_tasks, cast(int, default_nni_config["maxTrialNumber"]))
cmd = "nnictl create --config " + nni_config_filename + " --port 8088"

Expand All @@ -805,6 +806,7 @@ def _train_algo_in_nni(self, history: list[dict[str, Any]]) -> None:
n_trainings = len(import_bundle_algo_history(self.work_dir, only_trained=True))

cmd = "nnictl stop --all"
# pyrefly: ignore [bad-argument-type]
run_cmd(cmd.split(), check=True)
logger.info(f"NNI completes HPO on {name}")
last_total_tasks = n_trainings
Expand Down
3 changes: 3 additions & 0 deletions monai/apps/deepedit/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ def _randomize(self, d, key_label):
else:
logger.info(f"Not slice IDs for label: {key_label}")
sid = None
# pyrefly: ignore [unsupported-operation]
self.sid[key_label] = sid

def __call__(self, data: Mapping[Hashable, np.ndarray]) -> dict[Hashable, np.ndarray]:
Expand Down Expand Up @@ -561,6 +562,7 @@ def __init__(
self.guidance: dict[str, list[list[int]]] = {}

def randomize(self, data=None):
# pyrefly: ignore [unsupported-operation]
probability = data[self.probability]
self._will_interact = self.R.choice([True, False], p=[probability, 1.0 - probability])

Expand Down Expand Up @@ -885,6 +887,7 @@ def _randomize(self, d, key_label):
else:
logger.info(f"Not slice IDs for label: {key_label}")
sid = None
# pyrefly: ignore [unsupported-operation]
self.sid[key_label] = sid

def __call__(self, data: Mapping[Hashable, np.ndarray]) -> dict[Hashable, np.ndarray]:
Expand Down
1 change: 1 addition & 0 deletions monai/apps/deepgrow/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def _save_data_2d(vol_idx, vol_image, vol_label, dataset_dir, relative_path):
continue

# For all Labels
# pyrefly: ignore [missing-attribute]
unique_labels = np.unique(label.flatten())
unique_labels = unique_labels[unique_labels != 0]
unique_labels_count = max(unique_labels_count, len(unique_labels))
Expand Down
1 change: 1 addition & 0 deletions monai/apps/deepgrow/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ def __init__(self, guidance: str = "guidance", discrepancy: str = "discrepancy",
self._will_interact = None

def randomize(self, data=None):
# pyrefly: ignore [unsupported-operation]
probability = data[self.probability]
self._will_interact = self.R.choice([True, False], p=[probability, 1.0 - probability])

Expand Down
2 changes: 2 additions & 0 deletions monai/apps/detection/networks/retinanet_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ def forward(
)

# 4. Generate anchors and store it in self.anchors: List[Tensor]
# pyrefly: ignore [bad-argument-type]
self.generate_anchors(images, head_outputs)
# num_anchor_locs_per_level: List[int], list of HW or HWD for each level
num_anchor_locs_per_level = [x.shape[2:].numel() for x in head_outputs[self.cls_key]]
Expand All @@ -535,6 +536,7 @@ def forward(
# reshape to Tensor sized(B, sum(HWA), self.num_classes) for self.cls_key
# or (B, sum(HWA), 2* self.spatial_dims) for self.box_reg_key
# A = self.num_anchors_per_loc
# pyrefly: ignore [bad-argument-type]
head_outputs[key] = self._reshape_maps(head_outputs[key])

# 6(1). If during training, return losses
Expand Down
4 changes: 4 additions & 0 deletions monai/apps/detection/transforms/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,14 @@ def __call__(self, boxes: NdarrayTensor, src_spatial_size: Sequence[int] | int |
diff = od - zd
half = abs(diff) // 2
if diff > 0: # need padding (half, diff - half)
# pyrefly: ignore [bad-index, unsupported-operation]
zoomed_boxes[:, axis] = zoomed_boxes[:, axis] + half
# pyrefly: ignore [bad-index, unsupported-operation]
zoomed_boxes[:, axis + spatial_dims] = zoomed_boxes[:, axis + spatial_dims] + half
elif diff < 0: # need slicing (half, half + od)
# pyrefly: ignore [bad-index, unsupported-operation]
zoomed_boxes[:, axis] = zoomed_boxes[:, axis] - half
# pyrefly: ignore [bad-index, unsupported-operation]
zoomed_boxes[:, axis + spatial_dims] = zoomed_boxes[:, axis + spatial_dims] - half
return zoomed_boxes

Expand Down
2 changes: 2 additions & 0 deletions monai/apps/detection/transforms/box_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ def flip_boxes(
_flip_boxes: NdarrayTensor = boxes.clone() if isinstance(boxes, torch.Tensor) else deepcopy(boxes) # type: ignore[assignment]

for axis in flip_axes:
# pyrefly: ignore [bad-index, unsupported-operation]
_flip_boxes[:, axis + spatial_dims] = spatial_size[axis] - boxes[:, axis] - TO_REMOVE
# pyrefly: ignore [bad-index, unsupported-operation]
_flip_boxes[:, axis] = spatial_size[axis] - boxes[:, axis + spatial_dims] - TO_REMOVE

return _flip_boxes
Expand Down
2 changes: 2 additions & 0 deletions monai/apps/generation/maisi/networks/autoencoderkl_maisi.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,9 @@ def forward(self, x: torch.Tensor) -> torch.Tensor:

# update padding length if necessary
padding = 3
# pyrefly: ignore [unsupported-operation]
if padding % self.stride > 0:
# pyrefly: ignore [unsupported-operation]
padding = (padding // self.stride + 1) * self.stride
if self.print_info:
logger.info(f"Padding size: {padding}")
Expand Down
1 change: 1 addition & 0 deletions monai/apps/nnunet/nnunetv2_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ def convert_dataset(self):
modality = [modality]

create_new_dataset_json(
# pyrefly: ignore [bad-argument-type]
modality=modality,
num_foreground_classes=num_foreground_classes,
num_input_channels=num_input_channels,
Expand Down
1 change: 1 addition & 0 deletions monai/apps/pathology/transforms/post/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ def __call__(self, data):
d = dict(data)
for key in self.key_iterator(d):
offset = d[self.offset_key] if self.offset_key else None
# pyrefly: ignore [bad-argument-type]
centroid = self.converter(d[key], offset)
key_to_add = f"{key}_{self.centroid_key_postfix}"
if key_to_add in d:
Expand Down
1 change: 1 addition & 0 deletions monai/auto3dseg/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,5 @@ def evaluate(self, data: Any, **kwargs: Any) -> dict:
Args:
data: input data
"""
# pyrefly: ignore [missing-attribute]
return {k: v(data[k], **kwargs).tolist() for k, v in self.data.items() if (callable(v) and k in data)}
1 change: 1 addition & 0 deletions monai/auto3dseg/seg_summarizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def summarize(self, data: list[dict]) -> dict[str, dict]:

for analyzer in self.summary_analyzers:
if callable(analyzer):
# pyrefly: ignore [missing-attribute]
report.update({analyzer.stats_name: analyzer(data)})

return report
1 change: 1 addition & 0 deletions monai/bundle/reference_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ def iter_subconfigs(cls, id: str, config: Any) -> Iterator[tuple[str, str, Any]]
"""
for k, v in config.items() if isinstance(config, dict) else enumerate(config):
sub_id = f"{id}{cls.sep}{k}" if id != "" else f"{k}"
# pyrefly: ignore [invalid-yield]
yield k, sub_id, v

@classmethod
Expand Down
1 change: 1 addition & 0 deletions monai/bundle/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,7 @@ def create_workflow(
)

if config_file is not None:
# pyrefly: ignore [unexpected-keyword]
workflow_ = workflow_class(config_file=config_file, **_args)
else:
workflow_ = workflow_class(**_args)
Expand Down
3 changes: 3 additions & 0 deletions monai/bundle/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ def add_property(self, name: str, required: str, desc: str | None = None) -> Non
desc: descriptions for the property.
"""
if self.properties is None:
# pyrefly: ignore [bad-assignment]
self.properties = {}
if name in self.properties:
logger.warning(f"property '{name}' already exists in the properties list, overriding it.")
Expand Down Expand Up @@ -329,6 +330,7 @@ def _get_property(self, name: str, property: dict) -> Any:
elif name in self._props_vals:
value = self._props_vals[name]
elif name in self.parser.config[self.parser.meta_key]: # type: ignore[index]
# pyrefly: ignore [missing-attribute]
id = self.properties.get(name, None).get(BundlePropertyConfig.ID, None)
value = self.parser[id]
else:
Expand Down Expand Up @@ -621,6 +623,7 @@ def _check_optional_id(self, name: str, property: dict) -> bool:
else:
ref = self.parser.get(ref_id, None)
# for reference IDs that not refer to a property directly but using expressions, skip the check
# pyrefly: ignore [unsupported-operation]
if ref is not None and not ref.startswith(EXPR_KEY) and ref != ID_REF_KEY + id:
return False
return True
Expand Down
1 change: 1 addition & 0 deletions monai/data/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,7 @@ def _cachecheck(self, item_transformed):
item_k = kvikio_numpy.fromfile(
f"{hashfile}-{k}-{i}", dtype=meta_i_k["dtype"], like=cp.empty(())
)
# pyrefly: ignore [missing-attribute]
item_k = convert_to_tensor(item[i].reshape(meta_i_k["shape"]), device=f"cuda:{self.device}")
item[i].update({k: item_k, f"{k}_meta_dict": meta_i_k})
return item
Expand Down
1 change: 1 addition & 0 deletions monai/data/grid_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def __call__(
self, data: Mapping[Hashable, NdarrayTensor]
) -> Generator[tuple[Mapping[Hashable, NdarrayTensor], np.ndarray], None, None]:
d = dict(data)
# pyrefly: ignore [missing-attribute]
original_spatial_shape = d[first(self.keys)].shape[1:]

for patch in zip(*[self.patch_iter(d[key]) for key in self.keys]):
Expand Down
2 changes: 1 addition & 1 deletion monai/data/image_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from collections.abc import Callable, Iterable, Iterator, Sequence
from dataclasses import dataclass
from pathlib import Path
from typing import TYPE_CHECKING, Any, TypeAlias
from typing import TYPE_CHECKING, Any, TypeAlias # pyrefly: ignore [missing-module-attribute]

import numpy as np
from torch.utils.data._utils.collate import np_str_obj_array_pattern
Expand Down
2 changes: 2 additions & 0 deletions monai/data/wsi_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,10 @@ def __init__(
self.offset_limits = None
elif isinstance(offset_limits, tuple):
if isinstance(offset_limits[0], int):
# pyrefly: ignore [bad-assignment]
self.offset_limits = (offset_limits, offset_limits)
elif isinstance(offset_limits[0], tuple):
# pyrefly: ignore [bad-assignment]
self.offset_limits = offset_limits
else:
raise ValueError(
Expand Down
1 change: 1 addition & 0 deletions monai/data/wsi_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ def _get_metadata(
}
return metadata

# pyrefly: ignore [bad-override]
def get_data(
self,
wsi,
Expand Down
2 changes: 2 additions & 0 deletions monai/engines/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,11 +489,13 @@ def _iteration(self, engine: EnsembleEvaluator, batchdata: dict[str, torch.Tenso
if engine.amp:
with torch.autocast("cuda", **engine.amp_kwargs):
if isinstance(engine.state.output, dict):
# pyrefly: ignore [no-matching-overload]
engine.state.output.update(
{engine.pred_keys[idx]: engine.inferer(inputs, network, *args, **kwargs)}
)
else:
if isinstance(engine.state.output, dict):
# pyrefly: ignore [no-matching-overload]
engine.state.output.update(
{engine.pred_keys[idx]: engine.inferer(inputs, network, *args, **kwargs)}
)
Expand Down
1 change: 1 addition & 0 deletions monai/engines/trainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -774,4 +774,5 @@ def _compute_discriminator_loss() -> None:
engine.state.output[AdversarialKeys.DISCRIMINATOR_LOSS].backward()
engine.state.d_optimizer.step()

# pyrefly: ignore [bad-return]
return engine.state.output
1 change: 1 addition & 0 deletions monai/fl/client/monai_algo.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ def _get_data_key_stats(self, data, data_key, hist_bins, hist_range, output_path
dataroot=self.workflow.dataset_dir, # type: ignore
hist_bins=hist_bins,
hist_range=hist_range,
# pyrefly: ignore [bad-argument-type]
output_path=output_path,
histogram_only=self.histogram_only,
)
Expand Down
2 changes: 2 additions & 0 deletions monai/handlers/mlflow_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ def start(self, engine: Engine) -> None:
self._log_params(attrs)

if self.dataset_logger:
# pyrefly: ignore [bad-argument-type]
self.dataset_logger(self.dataset_dict)
else:
self._default_dataset_log(self.dataset_dict)
Expand All @@ -257,6 +258,7 @@ def _set_experiment(self):
else:
raise e

# pyrefly: ignore [missing-attribute]
if experiment.lifecycle_stage != mlflow.entities.LifecycleStage.ACTIVE:
raise ValueError(f"Cannot set a deleted experiment '{self.experiment_name}' as the active experiment")
self.experiment = experiment
Expand Down
1 change: 1 addition & 0 deletions monai/inferers/inferer.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,7 @@ def network_wrapper(

if isinstance(out, Mapping):
for k in out.keys():
# pyrefly: ignore [unsupported-operation]
out[k] = out[k].unsqueeze(dim=self.spatial_dim + 2)
return out

Expand Down
1 change: 1 addition & 0 deletions monai/losses/image_dissimilarity.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ def __init__(
if self.kernel_type == "gaussian":
self.register_buffer("preterm", 1 / (2 * sigma**2), persistent=False)
self.register_buffer("bin_centers", bin_centers[None, None, ...], persistent=False)

self.smooth_nr = float(smooth_nr)
self.smooth_dr = float(smooth_dr)

Expand Down
1 change: 1 addition & 0 deletions monai/metrics/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ def get_mask_edges(
or_vol = seg_pred | seg_gt
if not or_vol.any():
pred, gt = lib.zeros(seg_pred.shape, dtype=bool), lib.zeros(seg_gt.shape, dtype=bool)
# pyrefly: ignore [bad-return]
return (pred, gt) if spacing is None else (pred, gt, pred, gt)
channel_first = [seg_pred[None], seg_gt[None], or_vol[None]]
if spacing is None and not use_cucim: # cpu only erosion
Expand Down
16 changes: 8 additions & 8 deletions monai/networks/blocks/hyena.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,21 @@ class _DepthwiseFFTForward:
_spatial_dims: int # set by subclasses
fft_chunk_size: int = 0 # 0 = no chunking; set in subclass __init__

def forward(self, x: torch.Tensor) -> torch.Tensor:
spatial = x.shape[2:]
def forward(self, input: torch.Tensor) -> torch.Tensor:
spatial = input.shape[2:]
kernel_shape = self.weight.shape[2:] # type: ignore[attr-defined]
fft_dims = tuple(range(-self._spatial_dims, 0))
fft_size = [s + k - 1 for s, k in zip(spatial, kernel_shape)]
in_dtype = x.dtype
in_dtype = input.dtype

slices = (slice(None), slice(None)) + tuple(slice(k // 2, k // 2 + s) for s, k in zip(spatial, kernel_shape))

chunk = getattr(self, "fft_chunk_size", 0)
if chunk > 0 and x.shape[1] > chunk:
if chunk > 0 and input.shape[1] > chunk:
parts = []
for c0 in range(0, x.shape[1], chunk):
c1 = min(c0 + chunk, x.shape[1])
xc = x[:, c0:c1].float()
for c0 in range(0, input.shape[1], chunk):
c1 = min(c0 + chunk, input.shape[1])
xc = input[:, c0:c1].float()
kc = self.weight[c0:c1].squeeze(1).float() # type: ignore[attr-defined]
kc = kc.flip(list(range(1, self._spatial_dims + 1)))
xc_fft = torch.fft.rfftn(xc, s=fft_size, dim=fft_dims)
Expand All @@ -125,7 +125,7 @@ def forward(self, x: torch.Tensor) -> torch.Tensor:
del out_c
return torch.cat(parts, dim=1)

x_f32 = x.float()
x_f32 = input.float()
k_f32 = self.weight.squeeze(1).float() # type: ignore[attr-defined]
# PyTorch ``F.conv*`` computes cross-correlation; FFT computes convolution.
# Flip the kernel so the FFT output matches ``Conv{2,3}d`` exactly.
Expand Down
Loading