Skip to content

Conversation

@Hitendrasinhdata7
Copy link

Description

Implements 3D Radial Fourier Transform for medical imaging applications, addressing anisotropic resolution challenges and enabling rotation-invariant frequency analysis. This transform is specifically designed for medical images where voxel spacing often differs between axial, coronal, and sagittal planes (e.g., typical CT/MRI with different slice thickness vs in-plane resolution).

Medical Imaging Problem Addressed:

  • Anisotropic Resolution Normalization: Converts data to isotropic frequency domain representation
  • Rotation-Invariant Analysis: Radial frequency profiles remain consistent under 3D rotation
  • Acquisition Parameter Robustness: Reduces sensitivity to varying scan parameters across datasets

Key Features:

  • RadialFourier3D: Core transform for 3D radial frequency analysis with configurable radial bins
  • RadialFourierFeatures3D: Multi-scale frequency feature extraction for comprehensive analysis
  • Flexible Output Modes: Magnitude-only, phase-only, or complex outputs
  • Frequency Range Control: Optional maximum frequency cutoff for noise reduction
  • Inverse Transform Support: Approximate reconstruction for validation purposes
  • Medical Image Optimized: Handles common medical image shapes (batch, channel, depth, height, width)

Technical Implementation:

  • Location: monai/transforms/signal/radial_fourier.py
  • Tests: tests/test_radial_fourier.py (20/20 passing, comprehensive coverage)
  • Dependencies: Uses PyTorch's native FFT - no new dependencies
  • Performance: GPU-accelerated via PyTorch, O(N log N) complexity
  • Compatibility: Supports both PyTorch tensors and NumPy arrays
  • API Consistency: Follows MONAI transform conventions and typing

Usage Examples:

# Basic radial frequency analysis
from monai.transforms import RadialFourier3D
transform = RadialFourier3D(radial_bins=64, return_magnitude=True)
features = transform(image)  # Shape: (batch, 64)

# Full frequency analysis with phase information
transform_full = RadialFourier3D(radial_bins=None, return_magnitude=True, return_phase=True)
full_spectrum = transform_full(image)  # Full 3D spectrum with magnitude and phase

# Multi-scale feature extraction for ML pipelines
from monai.transforms import RadialFourierFeatures3D
feature_extractor = RadialFourierFeatures3D(
    n_bins_list=[16, 32, 64, 128],
    return_types=["magnitude", "phase"]
)
ml_features = feature_extractor(image)  # Comprehensive feature vector

…lysis

- Implement RadialFourier3D transform for radial frequency analysis
- Add RadialFourierFeatures3D for multi-scale feature extraction
- Include comprehensive tests (20/20 passing)
- Support for magnitude, phase, and complex outputs
- Handle anisotropic resolution in medical imaging
- Fix numpy compatibility and spatial dimension handling

Signed-off-by: Hitendrasinh Rathod<hitendrasinh.data7@gmail.com>
Signed-off-by: Hitendrasinh Rathod <Hitendrasinh.data7@gmail.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 21, 2025

📝 Walkthrough

Walkthrough

Adds a new monai.transforms.signal subpackage and a radial_fourier module providing RadialFourier3D (3D FFT-based forward/inverse, radial coordinate computation, optional radial binning, magnitude/phase outputs) and RadialFourierFeatures3D (multi-resolution feature extraction). Exposes these symbols in monai.transforms.signal.init and re-exports them from monai.transforms.init; removes SignalRandShift from top-level exports. Adds comprehensive tests in tests/test_radial_fourier.py covering shapes, dtypes, forward/inverse behavior, parameter validation, batching, multi-scale features, and API stability. Updates pyproject.toml pycln exclude patterns.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive Description covers medical problem, key features, implementation details, and usage examples. However, it doesn't explicitly check the template checklist boxes as required by the template. Complete the 'Types of changes' checklist section from the template to indicate which items apply (non-breaking change, tests added, documentation updated, etc.).
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title directly reflects the main change: a new 3D Radial Fourier Transform feature for medical image analysis, which matches the PR's primary contribution.
Docstring Coverage ✅ Passed Docstring coverage is 92.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
tests/test_radial_fourier.py (1)

76-88: Inverse transform test only checks shape, not reconstruction accuracy.

Consider adding an assertion that the reconstructed data is close to the original input to validate correctness.

         # Should have same shape
         self.assertEqual(reconstructed.shape, self.test_image_3d.shape)
+
+        # Should approximately reconstruct original
+        self.assertTrue(torch.allclose(reconstructed, self.test_image_3d, atol=1e-5))
monai/transforms/signal/radial_fourier.py (3)

137-144: Loop-based binning may be slow for large radial_bins.

Consider vectorized binning using torch.bucketize for better performance, though current implementation is correct.


34-62: Docstring missing Raises section.

Per coding guidelines, docstrings should document raised exceptions.

     Example:
         >>> transform = RadialFourier3D(radial_bins=64, return_magnitude=True)
         >>> image = torch.randn(1, 128, 128, 96)  # Batch, Height, Width, Depth
         >>> result = transform(image)  # Shape: (1, 64)
+
+    Raises:
+        ValueError: If max_frequency not in (0.0, 1.0], radial_bins < 1, or both
+            return_magnitude and return_phase are False.
     """

30-31: Unused import.

spatial is imported but never used.

-# Optional imports for type checking
-spatial, _ = optional_import("monai.utils", name="spatial")
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 15fd428 and cb0546d.

📒 Files selected for processing (4)
  • monai/transforms/__init__.py (1 hunks)
  • monai/transforms/signal/__init__.py (1 hunks)
  • monai/transforms/signal/radial_fourier.py (1 hunks)
  • tests/test_radial_fourier.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

Review the Python code for quality and correctness. Ensure variable names adhere to PEP8 style guides, are sensible and informative in regards to their function, though permitting simple names for loop and comprehension variables. Ensure routine names are meaningful in regards to their function and use verbs, adjectives, and nouns in a semantically appropriate way. Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings. Examine code for logical error or inconsistencies, and suggest what may be changed to addressed these. Suggest any enhancements for code improving efficiency, maintainability, comprehensibility, and correctness. Ensure new or modified definitions will be covered by existing or new unit tests.

Files:

  • tests/test_radial_fourier.py
  • monai/transforms/signal/radial_fourier.py
  • monai/transforms/signal/__init__.py
  • monai/transforms/__init__.py
🧬 Code graph analysis (3)
tests/test_radial_fourier.py (1)
monai/transforms/signal/radial_fourier.py (3)
  • RadialFourier3D (34-279)
  • RadialFourierFeatures3D (282-350)
  • inverse (239-279)
monai/transforms/signal/__init__.py (1)
monai/transforms/signal/radial_fourier.py (2)
  • RadialFourier3D (34-279)
  • RadialFourierFeatures3D (282-350)
monai/transforms/__init__.py (2)
monai/transforms/signal/array.py (1)
  • SignalRemoveFrequency (387-419)
monai/transforms/signal/radial_fourier.py (2)
  • RadialFourier3D (34-279)
  • RadialFourierFeatures3D (282-350)
🪛 Ruff (0.14.8)
monai/transforms/signal/radial_fourier.py

86-86: Avoid specifying long messages outside the exception class

(TRY003)


88-88: Avoid specifying long messages outside the exception class

(TRY003)


90-90: Avoid specifying long messages outside the exception class

(TRY003)


166-166: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (7)
monai/transforms/__init__.py (1)

379-381: LGTM!

New radial Fourier transforms are correctly imported and exported at the package level.

monai/transforms/signal/__init__.py (1)

11-17: LGTM!

Module docstring and exports are correctly set up.

tests/test_radial_fourier.py (2)

25-136: Good test coverage for RadialFourier3D.

Tests cover key scenarios including edge cases, type handling, and parameter validation.


138-193: Good test coverage for RadialFourierFeatures3D.

Multi-scale feature extraction and numpy compatibility are well tested.

monai/transforms/signal/radial_fourier.py (3)

64-91: LGTM!

Parameter validation is thorough and handles edge cases correctly.


239-279: LGTM!

Inverse transform correctly handles the non-binned case with proper FFT shift operations.


343-348: Edge case: when transforms list is empty, output = img may cause issues.

If img is a tensor and transforms is empty, output = img is returned. Then isinstance(img, np.ndarray) is False, so output.cpu().numpy() is never called. This is correct.

However, if img is already a numpy array and transforms is empty, the function returns the numpy array directly without conversion, which is the expected behavior.

- Add device parameter to _compute_radial_coordinates to prevent CPU/GPU mismatch
- Fix frequency mask expansion for multi-dimensional inputs
- Add reconstruction accuracy test assertion (with proper magnitude+phase for inverse)
- Add Raises section to docstring
- Remove unused import
- Address all review comments
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/test_radial_fourier.py (1)

35-35: Unused test fixture.

test_image_4d is created but never used in any test methods.

Proposed fix
-        self.test_image_4d = torch.randn(2, 1, 48, 64, 64, device=self.device)  # Batch, Channel, D, H, W
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between cb0546d and d12876d.

📒 Files selected for processing (2)
  • monai/transforms/signal/radial_fourier.py
  • tests/test_radial_fourier.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

Review the Python code for quality and correctness. Ensure variable names adhere to PEP8 style guides, are sensible and informative in regards to their function, though permitting simple names for loop and comprehension variables. Ensure routine names are meaningful in regards to their function and use verbs, adjectives, and nouns in a semantically appropriate way. Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings. Examine code for logical error or inconsistencies, and suggest what may be changed to addressed these. Suggest any enhancements for code improving efficiency, maintainability, comprehensibility, and correctness. Ensure new or modified definitions will be covered by existing or new unit tests.

Files:

  • tests/test_radial_fourier.py
  • monai/transforms/signal/radial_fourier.py
🧬 Code graph analysis (1)
tests/test_radial_fourier.py (1)
monai/transforms/signal/radial_fourier.py (3)
  • RadialFourier3D (34-285)
  • RadialFourierFeatures3D (288-356)
  • inverse (245-285)
🪛 Ruff (0.14.10)
monai/transforms/signal/radial_fourier.py

90-90: Avoid specifying long messages outside the exception class

(TRY003)


92-92: Avoid specifying long messages outside the exception class

(TRY003)


94-94: Avoid specifying long messages outside the exception class

(TRY003)


171-171: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: flake8-py3 (mypy)
  • GitHub Check: flake8-py3 (pytype)
  • GitHub Check: flake8-py3 (codeformat)
  • GitHub Check: quick-py3 (macOS-latest)
  • GitHub Check: packaging
  • GitHub Check: quick-py3 (windows-latest)
  • GitHub Check: build-docs
  • GitHub Check: quick-py3 (ubuntu-latest)
  • GitHub Check: min-dep-os (ubuntu-latest)
  • GitHub Check: min-dep-py3 (3.12)
  • GitHub Check: min-dep-py3 (3.9)
  • GitHub Check: min-dep-os (windows-latest)
  • GitHub Check: min-dep-pytorch (2.8.0)
  • GitHub Check: min-dep-py3 (3.11)
  • GitHub Check: min-dep-pytorch (2.6.0)
  • GitHub Check: min-dep-pytorch (2.5.1)
  • GitHub Check: min-dep-pytorch (2.7.1)
  • GitHub Check: min-dep-os (macOS-latest)
  • GitHub Check: min-dep-py3 (3.10)
🔇 Additional comments (8)
monai/transforms/signal/radial_fourier.py (8)

88-94: Parameter validation is correct.

All constraints are properly enforced. Static analysis flags long exception messages (TRY003), but these are clear and appropriate for ValueError.


96-118: LGTM!

Radial coordinate computation is correct. Device parameter properly addresses the prior CPU/GPU mismatch issue.


120-153: LGTM!

Radial spectrum binning logic is correct. Averaging is properly computed for complex values.


187-219: LGTM!

Radial binning with batch/channel preservation is correctly implemented. The reshape logic properly handles arbitrary batch dimensions.


220-228: LGTM!

Frequency masking correctly handles variable non-spatial dimensions. The fix from prior review properly addresses dimension broadcasting.


230-243: LGTM!

Output assembly correctly handles magnitude/phase extraction and concatenation. Type conversion preserves input format.


245-285: LGTM!

Inverse transform correctly reconstructs spatial data from magnitude/phase. FFT inversion sequence is correct, and normalization is properly reversed.


288-356: LGTM!

Multi-scale feature extraction correctly composes multiple RadialFourier3D transforms. Concatenation logic and type handling are correct. Empty bins_list case returns original image as expected.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
monai/transforms/signal/radial_fourier.py (1)

88-93: Optional: Consider custom exception classes.

Static analysis suggests custom exception classes for parameter validation instead of long messages in ValueError. This is a minor style improvement and can be deferred.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 66c4689 and 8fb969e.

📒 Files selected for processing (2)
  • monai/transforms/signal/radial_fourier.py
  • tests/test_radial_fourier.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

Review the Python code for quality and correctness. Ensure variable names adhere to PEP8 style guides, are sensible and informative in regards to their function, though permitting simple names for loop and comprehension variables. Ensure routine names are meaningful in regards to their function and use verbs, adjectives, and nouns in a semantically appropriate way. Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings. Examine code for logical error or inconsistencies, and suggest what may be changed to addressed these. Suggest any enhancements for code improving efficiency, maintainability, comprehensibility, and correctness. Ensure new or modified definitions will be covered by existing or new unit tests.

Files:

  • tests/test_radial_fourier.py
  • monai/transforms/signal/radial_fourier.py
🧬 Code graph analysis (1)
tests/test_radial_fourier.py (2)
monai/transforms/signal/radial_fourier.py (3)
  • RadialFourier3D (33-284)
  • RadialFourierFeatures3D (287-355)
  • inverse (244-284)
monai/utils/misc.py (1)
  • set_determinism (339-390)
🪛 Ruff (0.14.10)
monai/transforms/signal/radial_fourier.py

89-89: Avoid specifying long messages outside the exception class

(TRY003)


91-91: Avoid specifying long messages outside the exception class

(TRY003)


93-93: Avoid specifying long messages outside the exception class

(TRY003)


170-170: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: flake8-py3 (mypy)
  • GitHub Check: flake8-py3 (codeformat)
  • GitHub Check: quick-py3 (windows-latest)
  • GitHub Check: flake8-py3 (pytype)
  • GitHub Check: quick-py3 (ubuntu-latest)
  • GitHub Check: packaging
  • GitHub Check: quick-py3 (macOS-latest)
  • GitHub Check: build-docs
  • GitHub Check: min-dep-py3 (3.10)
  • GitHub Check: min-dep-pytorch (2.5.1)
  • GitHub Check: min-dep-os (ubuntu-latest)
  • GitHub Check: min-dep-py3 (3.12)
  • GitHub Check: min-dep-py3 (3.11)
  • GitHub Check: min-dep-os (macOS-latest)
  • GitHub Check: min-dep-pytorch (2.8.0)
  • GitHub Check: min-dep-py3 (3.9)
  • GitHub Check: min-dep-pytorch (2.6.0)
  • GitHub Check: min-dep-os (windows-latest)
  • GitHub Check: min-dep-pytorch (2.7.1)
🔇 Additional comments (8)
tests/test_radial_fourier.py (2)

41-138: Comprehensive test coverage.

The test methods cover output shapes, complex inputs, normalization, inverse transforms, determinism, numpy compatibility, parameter validation, custom spatial dimensions, and batch processing. Well done.


141-196: LGTM - proper test structure and coverage.

TestRadialFourierFeatures3D has correct setUp/tearDown structure and comprehensive tests for feature extraction scenarios.

monai/transforms/signal/radial_fourier.py (6)

95-117: Device handling correctly implemented.

The device parameter addition resolves the previous device mismatch issue. Implementation is correct.


119-152: LGTM - radial binning logic is correct.

The method correctly bins frequency components by radial distance and handles empty bins gracefully.


154-242: Core transform logic is sound.

The FFT computation, radial coordinate calculation, binning logic, and output extraction are correctly implemented. Previous device and mask expansion issues have been resolved.


244-284: Inverse transform correctly implemented.

The inverse handles the unbinned case with proper magnitude/phase reconstruction and FFT operations. Appropriately raises NotImplementedError for binned data that cannot be exactly inverted.


308-329: LGTM - multi-transform composition is correct.

The initialization correctly creates RadialFourier3D instances for all combinations of bin counts and return types.


331-355: Feature concatenation handles edge cases well.

The method correctly handles empty transforms, mixed numpy/tensor types, and preserves the input data type. Good defensive programming.

- Implements RadialFourier3D for anisotropic resolution normalization
- Adds RadialFourierFeatures3D for multi-scale frequency analysis
- Includes comprehensive test suite (20/20 passing)
- Adds version compatibility for older PyTorch/Python versions
- Follows MONAI transform conventions
- Exclude transforms/__init__.py from pycln to avoid import removal
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
monai/transforms/signal/radial_fourier.py (5)

28-29: Remove dead code.

Commented-out import adds no value.

Proposed fix
-# Optional imports for type checking
-# spatial, _ = optional_import("monai.utils", name="spatial")  # Commented out unused import

40-58: Docstring missing type annotations per Google style.

Args section should include types for each parameter. Per coding guidelines, docstrings should describe each variable with its type.

Example format
    Args:
        normalize (bool): if True, normalize the output by the number of voxels.
        return_magnitude (bool): if True, return magnitude of the complex result.
        return_phase (bool): if True, return phase of the complex result.
        radial_bins (Optional[int]): number of radial bins for frequency aggregation.
            If None, returns full 3D spectrum.
        max_frequency (float): maximum normalized frequency to include (0.0 to 1.0).
        spatial_dims (Union[int, Sequence[int]]): spatial dimensions to apply transform to.

123-123: Builtin sum() with generator of tensors starts from int 0.

Python's sum() initializes with 0, so 0 + tensor works but is inefficient. Consider explicit stacking.

Proposed fix
-        radial = torch.sqrt(sum(c**2 for c in mesh))
+        radial = torch.sqrt(torch.stack([c**2 for c in mesh]).sum(dim=0))

150-155: Loop-based binning may be slow for large volumes.

Vectorized binning with torch.bucketize and scatter_reduce would improve performance. Acceptable for now but consider optimization if profiling shows bottleneck.


305-315: Docstring incomplete per coding guidelines.

Missing type annotations in Args and no Raises section documented.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between ead0815 and 9c49afa.

📒 Files selected for processing (2)
  • monai/transforms/signal/radial_fourier.py
  • pyproject.toml
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

Review the Python code for quality and correctness. Ensure variable names adhere to PEP8 style guides, are sensible and informative in regards to their function, though permitting simple names for loop and comprehension variables. Ensure routine names are meaningful in regards to their function and use verbs, adjectives, and nouns in a semantically appropriate way. Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings. Examine code for logical error or inconsistencies, and suggest what may be changed to addressed these. Suggest any enhancements for code improving efficiency, maintainability, comprehensibility, and correctness. Ensure new or modified definitions will be covered by existing or new unit tests.

Files:

  • monai/transforms/signal/radial_fourier.py
🧬 Code graph analysis (1)
monai/transforms/signal/radial_fourier.py (3)
monai/networks/blocks/fft_utils_t.py (3)
  • fftshift (69-88)
  • ifftshift (91-110)
  • roll (45-66)
monai/transforms/transform.py (1)
  • Transform (244-297)
monai/utils/type_conversion.py (1)
  • convert_data_type (286-352)
🪛 Ruff (0.14.10)
monai/transforms/signal/radial_fourier.py

82-82: Avoid specifying long messages outside the exception class

(TRY003)


84-84: Avoid specifying long messages outside the exception class

(TRY003)


86-86: Avoid specifying long messages outside the exception class

(TRY003)


178-178: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: flake8-py3 (codeformat)
  • GitHub Check: quick-py3 (windows-latest)
  • GitHub Check: quick-py3 (macOS-latest)
  • GitHub Check: quick-py3 (ubuntu-latest)
  • GitHub Check: flake8-py3 (mypy)
  • GitHub Check: packaging
  • GitHub Check: flake8-py3 (pytype)
  • GitHub Check: build-docs
  • GitHub Check: min-dep-pytorch (2.7.1)
  • GitHub Check: min-dep-pytorch (2.5.1)
  • GitHub Check: min-dep-py3 (3.11)
  • GitHub Check: min-dep-pytorch (2.6.0)
  • GitHub Check: min-dep-pytorch (2.8.0)
  • GitHub Check: min-dep-py3 (3.9)
  • GitHub Check: min-dep-py3 (3.12)
  • GitHub Check: min-dep-os (macOS-latest)
  • GitHub Check: min-dep-py3 (3.10)
  • GitHub Check: min-dep-os (windows-latest)
  • GitHub Check: min-dep-os (ubuntu-latest)
🔇 Additional comments (3)
pyproject.toml (1)

39-39: LGTM!

Appropriate exclusion to prevent pycln from stripping the new public API re-exports.

monai/transforms/signal/radial_fourier.py (2)

180-183: FFT order: ifftshift before fftn assumes zero-frequency centered input.

Standard practice is fftn then fftshift. Pre-shifting input is unusual. Verify this is intentional for your use case.


340-363: LGTM!

Feature extraction and concatenation logic is sound.

- Remove dead code (commented import)
- Add proper type annotations to docstrings
- Fix sum() with generator for tensor operations
- Fix inverse transform logic when radial_bins=None and both magnitude+phase returned
- Add validation for empty feature extraction in RadialFourierFeatures3D
- Update test to expect ValueError for empty n_bins_list
- All tests passing
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
monai/transforms/signal/radial_fourier.py (3)

125-158: Radial binning logic is correct.

The loop-based approach with masking correctly averages spectrum values within each radial bin. While this could potentially be vectorized (e.g., using torch.bincount or scatter_add), the current implementation is clear and correct.


160-250: Forward transform implementation is sound.

The FFT computation, radial coordinate calculation with device parameter, frequency masking with correct dimension expansion, and output construction all work correctly. Previous review issues have been properly addressed.

Optional: Replace manual product calculations

At lines 186-188, 211-213, consider using math.prod() (Python 3.8+) for clarity:

         if self.normalize:
-            norm_factor = 1
-            for dim in spatial_shape:
-                norm_factor *= dim
+            import math
+            norm_factor = math.prod(spatial_shape)
             spectrum = spectrum / norm_factor
             # Reshape to 2D: (non_spatial_product, spatial_size)
-            non_spatial_product = 1
-            for dim in non_spatial_dims:
-                non_spatial_product *= dim
+            import math
+            non_spatial_product = math.prod(non_spatial_dims)

252-304: Inverse transform correctly handles magnitude+phase concatenation.

The validation at lines 275-280 and splitting at lines 282-284 properly address the previous review issue. The reconstruction logic is sound.

Optional: Use math.prod() for denormalization

At lines 292-294:

             if self.normalize:
-                shape_product = 1
-                for dim in original_shape:
-                    shape_product *= dim
+                import math
+                shape_product = math.prod(original_shape)
                 result = result * shape_product
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 9c49afa and c8eae2b.

📒 Files selected for processing (2)
  • monai/transforms/signal/radial_fourier.py
  • tests/test_radial_fourier.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_radial_fourier.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

Review the Python code for quality and correctness. Ensure variable names adhere to PEP8 style guides, are sensible and informative in regards to their function, though permitting simple names for loop and comprehension variables. Ensure routine names are meaningful in regards to their function and use verbs, adjectives, and nouns in a semantically appropriate way. Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings. Examine code for logical error or inconsistencies, and suggest what may be changed to addressed these. Suggest any enhancements for code improving efficiency, maintainability, comprehensibility, and correctness. Ensure new or modified definitions will be covered by existing or new unit tests.

Files:

  • monai/transforms/signal/radial_fourier.py
🪛 Ruff (0.14.10)
monai/transforms/signal/radial_fourier.py

80-80: Avoid specifying long messages outside the exception class

(TRY003)


82-82: Avoid specifying long messages outside the exception class

(TRY003)


84-84: Avoid specifying long messages outside the exception class

(TRY003)


176-176: Avoid specifying long messages outside the exception class

(TRY003)


276-280: Avoid specifying long messages outside the exception class

(TRY003)


340-340: Avoid specifying long messages outside the exception class

(TRY003)


342-342: Avoid specifying long messages outside the exception class

(TRY003)


374-374: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: quick-py3 (macOS-latest)
  • GitHub Check: quick-py3 (ubuntu-latest)
  • GitHub Check: flake8-py3 (mypy)
  • GitHub Check: quick-py3 (windows-latest)
  • GitHub Check: packaging
  • GitHub Check: flake8-py3 (pytype)
  • GitHub Check: build-docs
  • GitHub Check: flake8-py3 (codeformat)
  • GitHub Check: min-dep-py3 (3.11)
  • GitHub Check: min-dep-pytorch (2.7.1)
  • GitHub Check: min-dep-pytorch (2.8.0)
  • GitHub Check: min-dep-py3 (3.9)
  • GitHub Check: min-dep-pytorch (2.6.0)
  • GitHub Check: min-dep-py3 (3.10)
  • GitHub Check: min-dep-pytorch (2.5.1)
  • GitHub Check: min-dep-py3 (3.12)
  • GitHub Check: min-dep-os (ubuntu-latest)
  • GitHub Check: min-dep-os (windows-latest)
  • GitHub Check: min-dep-os (macOS-latest)
🔇 Additional comments (5)
monai/transforms/signal/radial_fourier.py (5)

1-27: Imports and module setup look good.

Clean imports, proper copyright header, necessary dependencies.


58-84: Parameter validation is thorough and correct.

The initialization properly validates all parameters and handles both scalar and sequence inputs for spatial_dims. The exception messages are clear and helpful for debugging.


86-123: Version compatibility fallbacks are well-implemented.

The device parameter correctly addresses the previous device mismatch issue. The fallback implementations for older PyTorch versions (fftfreq and meshgrid) maintain correct behavior.


327-354: Feature extractor initialization is well-validated.

The empty list validation (lines 339-342) correctly prevents misconfiguration, addressing the previous review concern. The transform creation logic properly handles the different return types.


356-380: Feature concatenation logic is correct.

The implementation properly handles type conversions between numpy and torch, validates against empty features (which shouldn't occur with validated parameters), and concatenates features along the last dimension consistently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant