diffct 2.4.3__py3-none-any.whl → 2.4.4__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.
diffct/__init__.py CHANGED
@@ -64,7 +64,7 @@ try:
64
64
  except ImportError:
65
65
  pass
66
66
 
67
- __version__ = '2.4.3'
67
+ __version__ = '2.4.4'
68
68
 
69
69
  __all__ = [
70
70
  'Projector',
diffct/analytical.py CHANGED
@@ -27,7 +27,7 @@ import math
27
27
 
28
28
  import torch
29
29
 
30
- from .constants import _DTYPE
30
+ from .constants import _DTYPE, _native_spacing
31
31
  from .utils import (
32
32
  DeviceManager,
33
33
  TorchCUDABridge,
@@ -431,7 +431,7 @@ def _parallel_weighted_backproject_raw(sinogram, ray_dir, det_origin, det_u_vec,
431
431
  _resolve_kernel('_parallel_2d_fbp_backproject_kernel')[grid, tpb, numba_stream](
432
432
  d_sino, n_views, n_det, d_reco, Nx, Ny,
433
433
  _DTYPE(detector_spacing), d_ray_dir, d_det_origin, d_det_u_vec,
434
- cx, cy, _DTYPE(voxel_spacing),
434
+ cx, cy, _native_spacing(voxel_spacing),
435
435
  )
436
436
 
437
437
  return reco * (1.0 / (2.0 * math.pi))
@@ -522,8 +522,9 @@ def _fan_weighted_backproject_raw(sinogram, src_pos, det_center, det_u_vec,
522
522
  _resolve_kernel('_fan_2d_fbp_backproject_kernel')[grid, tpb, numba_stream](
523
523
  d_sino, n_views, n_det, d_reco, Nx, Ny,
524
524
  _DTYPE(detector_spacing), d_src_pos, d_det_center, d_det_u_vec,
525
- cx, cy, _DTYPE(voxel_spacing),
526
- *(_DTYPE(value / voxel_spacing) for value in isocenter.tolist()),
525
+ cx, cy, _native_spacing(voxel_spacing),
526
+ *(_DTYPE(value if isinstance(voxel_spacing, (tuple, list)) else value / voxel_spacing)
527
+ for value in isocenter.tolist()),
527
528
  )
528
529
 
529
530
  return reco
@@ -584,8 +585,9 @@ def _cone_weighted_backproject_raw(sinogram, src_pos, det_center, det_u_vec, det
584
585
  d_sino, n_views, n_u, n_v, d_reco, Nx, Ny, Nz,
585
586
  _DTYPE(du), _DTYPE(dv),
586
587
  d_src_pos, d_det_center, d_det_u_vec, d_det_v_vec,
587
- cx, cy, cz, _DTYPE(voxel_spacing),
588
- *(_DTYPE(value / voxel_spacing) for value in isocenter.tolist()),
588
+ cx, cy, cz, _native_spacing(voxel_spacing),
589
+ *(_DTYPE(value if isinstance(voxel_spacing, (tuple, list)) else value / voxel_spacing)
590
+ for value in isocenter.tolist()),
589
591
  )
590
592
 
591
593
  # Convert back to (D, H, W) layout for the user.
@@ -637,7 +639,8 @@ def _analytical_transpose_raw(image, beam, geometry, parameters, isocenter, sino
637
639
  scale = (sdd_n / (2.0 * math.pi * sid_n)).view(
638
640
  (-1,) + (1,) * (len(sinogram_shape) - 1)
639
641
  )
640
- iso = tuple(_DTYPE(value / parameters[-1]) for value in isocenter.tolist())
642
+ iso = tuple(_DTYPE(value if isinstance(parameters[-1], (tuple, list)) else value / parameters[-1])
643
+ for value in isocenter.tolist())
641
644
 
642
645
  if beam == "cone":
643
646
  D, H, W, du, dv, spacing = parameters
@@ -647,7 +650,7 @@ def _analytical_transpose_raw(image, beam, geometry, parameters, isocenter, sino
647
650
  _resolve_kernel('_cone_3d_fdk_transpose_kernel')[grid, tpb, stream](
648
651
  d_sino, *sinogram_shape, d_image, W, H, D, _DTYPE(du), _DTYPE(dv),
649
652
  *d_geometry, _DTYPE(W * 0.5), _DTYPE(H * 0.5), _DTYPE(D * 0.5),
650
- _DTYPE(spacing), *iso,
653
+ _native_spacing(spacing), *iso,
651
654
  )
652
655
  else:
653
656
  pitch, H, W, spacing = parameters
@@ -657,7 +660,7 @@ def _analytical_transpose_raw(image, beam, geometry, parameters, isocenter, sino
657
660
  else '_fan_2d_fbp_transpose_kernel')
658
661
  kernel[grid, tpb, stream](
659
662
  d_sino, *sinogram_shape, d_image, W, H, _DTYPE(pitch), *d_geometry,
660
- _DTYPE(W * 0.5), _DTYPE(H * 0.5), _DTYPE(spacing), *iso,
663
+ _DTYPE(W * 0.5), _DTYPE(H * 0.5), _native_spacing(spacing), *iso,
661
664
  )
662
665
  return sinogram * scale
663
666
 
@@ -16,6 +16,7 @@ from .analytical import (
16
16
  fan_weighted_backproject, parallel_weighted_backproject,
17
17
  )
18
18
  from .backends import _zero_dependency, select_backend, voxel_spacing_tuple
19
+ from .constants import _native_spacing
19
20
  from .chunking import _memory_budget, _pixel_tiles
20
21
  from .distribution import Partition, preflight
21
22
  from .operators import _detector_spacing, _normalize_devices, _positive_int, _shape, _validate_trajectory
@@ -143,6 +144,9 @@ class AnalyticalExecution:
143
144
  self.rank = 3 if beam == "cone" else 2
144
145
  self.global_volume_shape = _shape(volume_shape, self.rank, "volume_shape")
145
146
  self.spacing = voxel_spacing_tuple(voxel_spacing, self.rank)
147
+ self.voxel_spacing = self.spacing if isinstance(voxel_spacing, (tuple, list)) else self.spacing[0]
148
+ if self.backend == "numba" and isinstance(self.voxel_spacing, tuple):
149
+ _native_spacing(self.voxel_spacing)
146
150
  self.pitch = _detector_spacing(detector_spacing, beam)
147
151
  self.devices = _normalize_devices(devices)
148
152
  if not isinstance(source, torch.Tensor):
@@ -336,14 +340,14 @@ class AnalyticalExecution:
336
340
  device=data.device, dtype=self.dtype)
337
341
  if self.beam == "parallel":
338
342
  geometry = (geometry[0], geometry[1] - centre, geometry[2])
339
- return parallel_weighted_backproject(data, *geometry, self.pitch[0], *shape, self.spacing[0])
343
+ return parallel_weighted_backproject(data, *geometry, self.pitch[0], *shape, self.voxel_spacing)
340
344
  geometry = (geometry[0] - centre, geometry[1] - centre, *geometry[2:])
341
345
  isocenter = self.isocenter.to(data.device) - centre
342
346
  if self.beam == "fan":
343
347
  return fan_weighted_backproject(data, *geometry, self.pitch[0], *shape,
344
- self.spacing[0], isocenter=isocenter)
348
+ self.voxel_spacing, isocenter=isocenter)
345
349
  return cone_weighted_backproject(data, *geometry, *shape, *self.pitch,
346
- self.spacing[0], isocenter=isocenter)
350
+ self.voxel_spacing, isocenter=isocenter)
347
351
 
348
352
  def _tile(self, spatial):
349
353
  shape = tuple(part.stop - part.start for part in spatial)