nabu 2024.2.4__py3-none-any.whl → 2025.1.0.dev4__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.
Files changed (164) hide show
  1. doc/doc_config.py +32 -0
  2. nabu/__init__.py +1 -1
  3. nabu/app/bootstrap_stitching.py +4 -2
  4. nabu/app/cast_volume.py +7 -13
  5. nabu/app/cli_configs.py +0 -5
  6. nabu/app/compare_volumes.py +1 -1
  7. nabu/app/composite_cor.py +2 -4
  8. nabu/app/correct_rot.py +0 -8
  9. nabu/app/diag_to_pix.py +5 -6
  10. nabu/app/diag_to_rot.py +10 -11
  11. nabu/app/multicor.py +1 -1
  12. nabu/app/parse_reconstruction_log.py +1 -0
  13. nabu/app/prepare_weights_double.py +1 -2
  14. nabu/app/reconstruct_helical.py +1 -5
  15. nabu/app/reduce_dark_flat.py +0 -2
  16. nabu/app/rotate.py +3 -1
  17. nabu/app/tests/test_reduce_dark_flat.py +2 -2
  18. nabu/app/validator.py +1 -4
  19. nabu/cuda/convolution.py +1 -1
  20. nabu/cuda/fft.py +1 -1
  21. nabu/cuda/medfilt.py +1 -1
  22. nabu/cuda/padding.py +1 -1
  23. nabu/cuda/src/cone.cu +19 -9
  24. nabu/cuda/src/hierarchical_backproj.cu +16 -0
  25. nabu/cuda/utils.py +2 -2
  26. nabu/estimation/alignment.py +17 -31
  27. nabu/estimation/cor.py +23 -29
  28. nabu/estimation/cor_sino.py +2 -8
  29. nabu/estimation/focus.py +4 -8
  30. nabu/estimation/tests/test_alignment.py +2 -0
  31. nabu/estimation/tests/test_tilt.py +1 -1
  32. nabu/estimation/tilt.py +5 -4
  33. nabu/io/cast_volume.py +5 -5
  34. nabu/io/detector_distortion.py +5 -6
  35. nabu/io/reader.py +3 -3
  36. nabu/io/reader_helical.py +5 -4
  37. nabu/io/tests/test_cast_volume.py +2 -2
  38. nabu/io/tests/test_readers.py +4 -4
  39. nabu/io/tests/test_writers.py +2 -2
  40. nabu/io/utils.py +8 -4
  41. nabu/io/writer.py +1 -2
  42. nabu/misc/fftshift.py +1 -1
  43. nabu/misc/fourier_filters.py +1 -1
  44. nabu/misc/histogram.py +1 -1
  45. nabu/misc/histogram_cuda.py +1 -1
  46. nabu/misc/padding_base.py +1 -1
  47. nabu/misc/rotation.py +1 -1
  48. nabu/misc/rotation_cuda.py +1 -1
  49. nabu/misc/tests/test_binning.py +1 -1
  50. nabu/misc/transpose.py +1 -1
  51. nabu/misc/unsharp.py +1 -1
  52. nabu/misc/unsharp_cuda.py +1 -1
  53. nabu/misc/unsharp_opencl.py +1 -1
  54. nabu/misc/utils.py +1 -1
  55. nabu/opencl/fft.py +1 -1
  56. nabu/opencl/padding.py +1 -1
  57. nabu/opencl/utils.py +8 -8
  58. nabu/pipeline/config.py +2 -2
  59. nabu/pipeline/config_validators.py +4 -3
  60. nabu/pipeline/datadump.py +3 -3
  61. nabu/pipeline/estimators.py +6 -6
  62. nabu/pipeline/fullfield/chunked.py +4 -5
  63. nabu/pipeline/fullfield/dataset_validator.py +0 -1
  64. nabu/pipeline/fullfield/nabu_config.py +2 -1
  65. nabu/pipeline/fullfield/reconstruction.py +9 -8
  66. nabu/pipeline/helical/dataset_validator.py +3 -4
  67. nabu/pipeline/helical/fbp.py +4 -4
  68. nabu/pipeline/helical/filtering.py +5 -4
  69. nabu/pipeline/helical/gridded_accumulator.py +9 -10
  70. nabu/pipeline/helical/helical_chunked_regridded.py +1 -0
  71. nabu/pipeline/helical/helical_reconstruction.py +10 -7
  72. nabu/pipeline/helical/helical_utils.py +1 -2
  73. nabu/pipeline/helical/nabu_config.py +1 -0
  74. nabu/pipeline/helical/span_strategy.py +1 -0
  75. nabu/pipeline/helical/weight_balancer.py +1 -2
  76. nabu/pipeline/tests/__init__.py +0 -0
  77. nabu/pipeline/utils.py +1 -1
  78. nabu/pipeline/writer.py +1 -1
  79. nabu/preproc/alignment.py +0 -10
  80. nabu/preproc/ctf.py +8 -8
  81. nabu/preproc/ctf_cuda.py +1 -1
  82. nabu/preproc/double_flatfield_cuda.py +2 -2
  83. nabu/preproc/double_flatfield_variable_region.py +0 -1
  84. nabu/preproc/flatfield.py +1 -1
  85. nabu/preproc/flatfield_cuda.py +1 -2
  86. nabu/preproc/flatfield_variable_region.py +3 -3
  87. nabu/preproc/phase.py +2 -4
  88. nabu/preproc/phase_cuda.py +2 -2
  89. nabu/preproc/shift_cuda.py +0 -1
  90. nabu/preproc/tests/test_ctf.py +3 -3
  91. nabu/preproc/tests/test_double_flatfield.py +1 -1
  92. nabu/preproc/tests/test_flatfield.py +1 -1
  93. nabu/preproc/tests/test_vshift.py +4 -1
  94. nabu/processing/azim.py +2 -2
  95. nabu/processing/convolution_cuda.py +6 -4
  96. nabu/processing/fft_base.py +1 -1
  97. nabu/processing/fft_cuda.py +19 -8
  98. nabu/processing/fft_opencl.py +9 -4
  99. nabu/processing/fftshift.py +1 -1
  100. nabu/processing/histogram.py +1 -1
  101. nabu/processing/muladd.py +0 -1
  102. nabu/processing/padding_base.py +1 -1
  103. nabu/processing/padding_cuda.py +0 -1
  104. nabu/processing/processing_base.py +1 -1
  105. nabu/processing/tests/test_fft.py +1 -1
  106. nabu/processing/tests/test_fftshift.py +1 -1
  107. nabu/processing/tests/test_medfilt.py +1 -3
  108. nabu/processing/tests/test_padding.py +1 -1
  109. nabu/processing/tests/test_roll.py +1 -1
  110. nabu/processing/unsharp_opencl.py +1 -1
  111. nabu/reconstruction/astra.py +245 -0
  112. nabu/reconstruction/cone.py +9 -4
  113. nabu/reconstruction/fbp_base.py +2 -2
  114. nabu/reconstruction/filtering_cuda.py +1 -1
  115. nabu/reconstruction/hbp.py +16 -3
  116. nabu/reconstruction/mlem.py +0 -1
  117. nabu/reconstruction/projection.py +3 -5
  118. nabu/reconstruction/sinogram.py +1 -1
  119. nabu/reconstruction/sinogram_cuda.py +0 -1
  120. nabu/reconstruction/tests/test_cone.py +76 -3
  121. nabu/reconstruction/tests/test_deringer.py +2 -2
  122. nabu/reconstruction/tests/test_fbp.py +1 -1
  123. nabu/reconstruction/tests/test_halftomo.py +27 -1
  124. nabu/reconstruction/tests/test_mlem.py +3 -2
  125. nabu/reconstruction/tests/test_projector.py +7 -2
  126. nabu/reconstruction/tests/test_sino_normalization.py +0 -1
  127. nabu/resources/dataset_analyzer.py +4 -4
  128. nabu/resources/gpu.py +4 -4
  129. nabu/resources/logger.py +4 -4
  130. nabu/resources/nxflatfield.py +2 -2
  131. nabu/resources/tests/test_nxflatfield.py +4 -4
  132. nabu/stitching/alignment.py +1 -4
  133. nabu/stitching/config.py +19 -16
  134. nabu/stitching/frame_composition.py +8 -10
  135. nabu/stitching/overlap.py +2 -2
  136. nabu/stitching/slurm_utils.py +2 -2
  137. nabu/stitching/stitcher/base.py +2 -0
  138. nabu/stitching/stitcher/dumper/base.py +0 -1
  139. nabu/stitching/stitcher/dumper/postprocessing.py +1 -1
  140. nabu/stitching/stitcher/post_processing.py +6 -6
  141. nabu/stitching/stitcher/pre_processing.py +13 -11
  142. nabu/stitching/stitcher/single_axis.py +3 -4
  143. nabu/stitching/stitcher_2D.py +2 -1
  144. nabu/stitching/tests/test_config.py +7 -8
  145. nabu/stitching/tests/test_sample_normalization.py +1 -1
  146. nabu/stitching/tests/test_slurm_utils.py +1 -2
  147. nabu/stitching/tests/test_z_postprocessing_stitching.py +1 -1
  148. nabu/stitching/tests/test_z_preprocessing_stitching.py +4 -4
  149. nabu/stitching/utils/tests/__init__.py +0 -0
  150. nabu/stitching/utils/tests/test_post-processing.py +1 -0
  151. nabu/stitching/utils/utils.py +10 -12
  152. nabu/tests.py +0 -3
  153. nabu/testutils.py +30 -8
  154. nabu/utils.py +28 -18
  155. {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/METADATA +25 -25
  156. nabu-2025.1.0.dev4.dist-info/RECORD +320 -0
  157. {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/WHEEL +1 -1
  158. nabu/io/tests/test_detector_distortion.py +0 -178
  159. nabu/resources/tests/test_extract.py +0 -9
  160. nabu-2024.2.4.dist-info/RECORD +0 -318
  161. /nabu/{stitching → app}/tests/__init__.py +0 -0
  162. {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/LICENSE +0 -0
  163. {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/entry_points.txt +0 -0
  164. {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/top_level.txt +0 -0
nabu/io/writer.py CHANGED
@@ -13,7 +13,6 @@ try:
13
13
  except:
14
14
  from h5py import File as HDF5File
15
15
  from tomoscan.esrf import RawVolume
16
- from tomoscan.esrf.volume.jp2kvolume import has_glymur as __have_jp2k__
17
16
  from .. import version as nabu_version
18
17
  from ..utils import merged_shape
19
18
  from .utils import convert_dict_values
@@ -183,7 +182,7 @@ class NXVolVolume(NXProcessWriter):
183
182
  volume_basename = file_prefix = kwargs.get("volume_basename", None)
184
183
  start_index = kwargs.get("start_index", None)
185
184
  overwrite = kwargs.get("overwrite", False)
186
- data_path = entry = kwargs.get("data_path", None)
185
+ entry = kwargs.get("data_path", None)
187
186
  self._process_name = kwargs.get("process_name", "reconstruction")
188
187
  if any([param is None for param in [folder, volume_basename, start_index, entry]]):
189
188
  raise ValueError("Need the following parameters: folder, volume_basename, start_index, data_path")
nabu/misc/fftshift.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.fftshift import *
1
+ from ..processing.fftshift import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
@@ -1,7 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
1
  """
3
2
  Fourier filters.
4
3
  """
4
+
5
5
  from functools import lru_cache
6
6
  import numpy as np
7
7
  import scipy.special as spspe
nabu/misc/histogram.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.histogram import *
1
+ from ..processing.histogram import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
@@ -1,4 +1,4 @@
1
- from ..processing.histogram_cuda import *
1
+ from ..processing.histogram_cuda import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
nabu/misc/padding_base.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.padding_base import *
1
+ from ..processing.padding_base import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
nabu/misc/rotation.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.rotation import *
1
+ from ..processing.rotation import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
@@ -1,4 +1,4 @@
1
- from ..processing.rotation_cuda import *
1
+ from ..processing.rotation_cuda import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
@@ -1,7 +1,7 @@
1
1
  from itertools import product
2
2
  import numpy as np
3
3
  import pytest
4
- from nabu.misc.binning import *
4
+ from nabu.misc.binning import binning
5
5
 
6
6
 
7
7
  @pytest.fixture(scope="class")
nabu/misc/transpose.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.transpose import *
1
+ from ..processing.transpose import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
nabu/misc/unsharp.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.unsharp import *
1
+ from ..processing.unsharp import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning("nabu.misc.unsharp has been moved to nabu.processing.unsharp", do_print=True, func_name="unsharp")
nabu/misc/unsharp_cuda.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.unsharp_cuda import *
1
+ from ..processing.unsharp_cuda import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
@@ -1,4 +1,4 @@
1
- from ..processing.unsharp_opencl import *
1
+ from ..processing.unsharp_opencl import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
nabu/misc/utils.py CHANGED
@@ -41,7 +41,7 @@ def psnr(img1, img2):
41
41
  #
42
42
 
43
43
 
44
- class ConvolutionInfos(object):
44
+ class ConvolutionInfos:
45
45
  allowed_axes = {
46
46
  "1D": [None],
47
47
  "separable_2D_1D_2D": [None, (0, 1), (1, 0)],
nabu/opencl/fft.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.fft_opencl import *
1
+ from ..processing.fft_opencl import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
nabu/opencl/padding.py CHANGED
@@ -1,4 +1,4 @@
1
- from ..processing.padding_opencl import *
1
+ from ..processing.padding_opencl import * # noqa: F403
2
2
  from ..utils import deprecation_warning
3
3
 
4
4
  deprecation_warning(
nabu/opencl/utils.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import numpy as np
2
- from ..utils import check_supported
2
+ from ..utils import check_supported, first_generator_item
3
3
 
4
4
  try:
5
5
  import pyopencl as cl
@@ -138,11 +138,11 @@ def collect_opencl_gpus():
138
138
  Return a dictionary of platforms and brief description of each OpenCL-compatible
139
139
  GPU with a few fields
140
140
  """
141
- gpus, error_msg = detect_opencl_gpus()
141
+ gpus_detected, error_msg = detect_opencl_gpus()
142
142
  if error_msg is not None:
143
143
  return None
144
144
  opencl_gpus = {}
145
- for platform, gpus in gpus.items():
145
+ for platform, gpus in gpus_detected.items():
146
146
  for gpu_id, gpu in gpus.items():
147
147
  if platform not in opencl_gpus:
148
148
  opencl_gpus[platform] = {}
@@ -215,22 +215,22 @@ def pick_opencl_cpu_platform(opencl_cpus):
215
215
  raise ValueError("No CPU to pick")
216
216
  name2device = {}
217
217
  for platform, devices in opencl_cpus.items():
218
- for device_id, device_desc in devices.items():
218
+ for device_id, device_desc in devices.items(): # noqa: PERF102
219
219
  name2device.setdefault(device_desc["name"], [])
220
220
  name2device[device_desc["name"]].append(platform)
221
221
  if len(name2device) > 1:
222
222
  raise ValueError("Expected at most one CPU but got %d: %s" % (len(name2device), list(name2device.keys())))
223
- cpu_name = list(name2device.keys())[0]
223
+ cpu_name = first_generator_item(name2device.keys())
224
224
  platforms = name2device[cpu_name]
225
225
  # Several platforms for the same CPU
226
226
  res = opencl_cpus[platforms[0]]
227
- if len(platforms) > 1:
227
+ if len(platforms) > 1: # noqa: SIM102
228
228
  if "intel" in cpu_name.lower():
229
229
  for platform in platforms:
230
230
  if "intel" in platform.lower():
231
231
  res = opencl_cpus[platform]
232
232
  #
233
- return res[list(res.keys())[0]]
233
+ return res[first_generator_item(res.keys())]
234
234
 
235
235
 
236
236
  def allocate_texture(ctx, shape, support_1D=False):
@@ -289,4 +289,4 @@ def copy_to_texture(queue, dst_texture, src_array, dtype=np.float32):
289
289
  src_array = np.ascontiguousarray(src_array, dtype=dtype)
290
290
  return cl.enqueue_copy(queue, dst_texture, src_array, origin=(0, 0), region=shape[::-1])
291
291
  else:
292
- raise ValueError("Unknown source array type")
292
+ raise TypeError("Unknown source array type")
nabu/pipeline/config.py CHANGED
@@ -156,7 +156,7 @@ def _extract_nabuconfig_section(section, default_config):
156
156
 
157
157
  def _extract_nabuconfig_keyvals(default_config):
158
158
  res = {}
159
- for section in default_config.keys():
159
+ for section in default_config:
160
160
  res[section] = _extract_nabuconfig_section(section, default_config)
161
161
  return res
162
162
 
@@ -257,7 +257,7 @@ def overwrite_config(conf, overwritten_params):
257
257
  if section not in conf:
258
258
  raise ValueError("Unknown section %s" % section)
259
259
  current_section = conf[section]
260
- for key in params.keys():
260
+ for key in params:
261
261
  if key not in current_section:
262
262
  raise ValueError("Unknown parameter '%s' in section '%s'" % (key, section))
263
263
  conf[section][key] = overwritten_params[section][key]
@@ -1,8 +1,9 @@
1
+ # ruff: noqa: F405
1
2
  import os
2
3
 
3
4
  path = os.path
4
5
  from ..utils import check_supported, is_writeable
5
- from .params import *
6
+ from .params import * # noqa: F403
6
7
 
7
8
  """
8
9
  A validator is a function with
@@ -310,7 +311,7 @@ def optional_nonzero_float_validator(val):
310
311
  assert error is None, "Invalid number"
311
312
  else:
312
313
  val_float = None
313
- if val_float is not None:
314
+ if val_float is not None: # noqa: SIM102
314
315
  if abs(val_float) < 1e-6:
315
316
  val_float = None
316
317
  return val_float
@@ -323,7 +324,7 @@ def optional_tuple_of_floats_validator(val):
323
324
  err_msg = "Expected a tuple of two numbers, but got %s" % val
324
325
  try:
325
326
  res = tuple(float(x) for x in val.strip("()").split(","))
326
- except Exception as exc:
327
+ except Exception:
327
328
  raise ValueError(err_msg)
328
329
  if len(res) != 2:
329
330
  raise ValueError(err_msg)
nabu/pipeline/datadump.py CHANGED
@@ -126,7 +126,7 @@ class DataDumpManager:
126
126
  read_opts = self.processing_options["read_chunk"]
127
127
  if read_opts.get("process_file", None) is None:
128
128
  return None
129
- dump_start_z, dump_end_z = read_opts["dump_start_z"], read_opts["dump_end_z"]
129
+ dump_start_z, dump_end_z = read_opts["dump_start_z"], read_opts["dump_end_z"] # noqa: F841
130
130
  relative_start_z = self.z_min - dump_start_z
131
131
  relative_end_z = relative_start_z + self.delta_z
132
132
  # When using binning, every step after "read" results in smaller-sized data.
@@ -139,7 +139,7 @@ class DataDumpManager:
139
139
 
140
140
  def _check_resume_from_step(self):
141
141
  read_opts = self.processing_options["read_chunk"]
142
- expected_radios_shape = get_hdf5_dataset_shape(
142
+ expected_radios_shape = get_hdf5_dataset_shape( # noqa: F841
143
143
  read_opts["process_file"],
144
144
  read_opts["process_h5_path"],
145
145
  sub_region=self.get_read_dump_subregion(),
@@ -151,7 +151,7 @@ class DataDumpManager:
151
151
  return
152
152
  writer = self.data_dump[step_name]
153
153
  self.logger.info("Dumping data to %s" % writer.fname)
154
- if __has_pycuda__:
154
+ if __has_pycuda__: # noqa: SIM102
155
155
  if isinstance(data, garray.GPUArray):
156
156
  data = data.get()
157
157
 
@@ -298,7 +298,7 @@ class SinoCORFinder(CORFinderBase):
298
298
  """
299
299
  Initialize a SinoCORFinder object.
300
300
 
301
- Other parameters
301
+ Other Parameters
302
302
  ----------------
303
303
  The following keys can be set in cor_options.
304
304
 
@@ -341,7 +341,7 @@ class SinoCORFinder(CORFinderBase):
341
341
  self.angles = self.dataset_info.rotation_angles[::subsampling]
342
342
  self.subsampling = subsampling
343
343
  else: # Angular step
344
- raise NotImplementedError()
344
+ raise NotImplementedError
345
345
 
346
346
  def _load_raw_sinogram(self):
347
347
  if self.slice_idx is None:
@@ -441,7 +441,7 @@ class CompositeCORFinder(CORFinderBase):
441
441
 
442
442
  search_methods = {
443
443
  "composite-coarse-to-fine": {
444
- "class": CenterOfRotation, # Hack. Not used. Everything is done in the find_cor() func.
444
+ "class": CenterOfRotation, # Not used. Everything is done in the find_cor() func.
445
445
  }
446
446
  }
447
447
  _default_cor_options = {"low_pass": 0.4, "high_pass": 10, "side": "near", "near_pos": 0, "near_width": 40}
@@ -786,7 +786,7 @@ class CompositeCORFinder(CORFinderBase):
786
786
  elif self.norm_order == 1:
787
787
  return self.error_metric_l1(common_right, common_left, common_blurred_right, common_blurred_left)
788
788
  else:
789
- assert False, "this cannot happen"
789
+ raise RuntimeError("this cannot happen")
790
790
 
791
791
  def error_metric_l2(self, common_right, common_left):
792
792
  common = common_right - common_left
@@ -818,10 +818,10 @@ def oversample(radio, ovs_s):
818
818
  # Pre-initialisation: The original data falls exactly on the following strided positions in the new data array.
819
819
  result[:: ovs_s[0], :: ovs_s[1]] = radio
820
820
 
821
- for k in range(0, ovs_s[0]):
821
+ for k in range(ovs_s[0]):
822
822
  # interpolation coefficient for axis 0
823
823
  g = k / ovs_s[0]
824
- for i in range(0, ovs_s[1]):
824
+ for i in range(ovs_s[1]):
825
825
  if i == 0 and k == 0:
826
826
  # this case subset was already exactly matched from before the present double loop,
827
827
  # in the pre-initialisation line.
@@ -18,7 +18,7 @@ from ...preproc.phase import PaganinPhaseRetrieval
18
18
  from ...preproc.ctf import CTFPhaseRetrieval, GeoPars
19
19
  from ...reconstruction.sinogram import SinoNormalization
20
20
  from ...reconstruction.filtering import SinoFilter
21
- from ...reconstruction.mlem import __have_corrct__, MLEMReconstructor
21
+ from ...reconstruction.mlem import MLEMReconstructor
22
22
  from ...processing.rotation import Rotation
23
23
  from ...reconstruction.rings import MunchDeringer, SinoMeanDeringer, VoDeringer
24
24
  from ...processing.unsharp import UnsharpMask
@@ -99,7 +99,6 @@ class ChunkedPipeline:
99
99
 
100
100
  Notes
101
101
  ------
102
-
103
102
  Using `margin` results in a lesser number of reconstructed slices.
104
103
  More specifically, if `margin = (V, H)`, then there will be `delta_z - 2*V`
105
104
  reconstructed slices (if the sub-region is in the middle of the volume)
@@ -175,7 +174,7 @@ class ChunkedPipeline:
175
174
  Data volume sub-region, in the form ((start_a, end_a), (start_z, end_z), (start_x, end_x))
176
175
  where the data volume has a layout (angles, Z, X)
177
176
  """
178
- n_angles = self.dataset_info.n_angles
177
+ # n_angles = self.dataset_info.n_angles
179
178
  n_x, n_z = self.dataset_info.radio_dims
180
179
  c_a, c_z, c_x = self.chunk_shape
181
180
  if sub_region is None:
@@ -190,7 +189,7 @@ class ChunkedPipeline:
190
189
  # check sub-region
191
190
  for i, start_end in enumerate(sub_region):
192
191
  start, end = start_end
193
- if start is not None and end is not None:
192
+ if start is not None and end is not None: # noqa: SIM102
194
193
  if end - start != self.chunk_shape[i]:
195
194
  raise ValueError(
196
195
  "Invalid (start, end)=(%d, %d) for sub-region (dimension %d): chunk shape is %s, but %d-%d=%d != %d"
@@ -635,7 +634,7 @@ class ChunkedPipeline:
635
634
  if options["method"] == "mlem" and options["implementation"] in (None, "corrct"):
636
635
  self.reconstruction = self.MLEMClass( # pylint: disable=E1102
637
636
  (self.radios_shape[1],) + self.sino_shape,
638
- angles_rad=-options["angles"], # WARNING: mind the sign...
637
+ angles_rad=options["angles"],
639
638
  shifts_uv=self.dataset_info.translations, # In config file, one line per proj, each line is (tu,tv). Corrct expects one col per proj and (tv,tu).
640
639
  cor=options["rotation_axis_position"],
641
640
  n_iterations=options["iterations"],
@@ -1,4 +1,3 @@
1
- import os
2
1
  from ..dataset_validator import DatasetValidatorBase
3
2
 
4
3
 
@@ -1,4 +1,5 @@
1
- from ..config_validators import *
1
+ # ruff: noqa: F405
2
+ from ..config_validators import * # noqa: F403
2
3
 
3
4
  nabu_config = {
4
5
  "dataset": {
@@ -7,7 +7,7 @@ from silx.io import get_data
7
7
  from silx.io.url import DataUrl
8
8
  from tomoscan.esrf.volume.singleframebase import VolumeSingleFrameBase
9
9
  from ... import version as nabu_version
10
- from ...utils import check_supported, subdivide_into_overlapping_segment
10
+ from ...utils import check_supported, first_generator_item, subdivide_into_overlapping_segment
11
11
  from ...resources.logger import LoggerOrPrint
12
12
  from ...resources.utils import is_hdf5_extension
13
13
  from ...io.writer import merge_hdf5_files, NXProcessWriter
@@ -61,7 +61,7 @@ class FullFieldReconstructor:
61
61
  Dictionary with cuda options passed to `nabu.cuda.processing.CudaProcessing`
62
62
 
63
63
 
64
- Other parameters
64
+ Other Parameters
65
65
  -----------------
66
66
  Advanced options can be passed in the 'extra_options' dictionary. These can be:
67
67
 
@@ -132,7 +132,7 @@ class FullFieldReconstructor:
132
132
  if len(avail_gpus) == 0:
133
133
  return
134
134
  # pick first GPU by default. TODO: handle user's nabu_config["resources"]["gpu_id"]
135
- self.resources["gpu_id"] = self._gpu_id = list(avail_gpus.keys())[0]
135
+ self.resources["gpu_id"] = self._gpu_id = first_generator_item(avail_gpus.keys())
136
136
 
137
137
  def _get_backend(self, backend, cuda_options):
138
138
  self._pipeline_cls = ChunkedPipeline
@@ -355,8 +355,8 @@ class FullFieldReconstructor:
355
355
  d2 = rec_cfg["sample_detector_dist"]
356
356
  n_z, _ = self.process_config.radio_shape(binning=True)
357
357
 
358
- delta_z = self.process_config.rec_delta_z # accounts_for_binning
359
- overlap = ceil(delta_z * d2 / (d1 + d2)) # sqrt(2) missing ?
358
+ # delta_z = self.process_config.rec_delta_z # accounts_for_binning
359
+ # overlap = ceil(delta_z * d2 / (d1 + d2)) # sqrt(2) missing ?
360
360
 
361
361
  max_overlap = ceil(n_z * d2 / (d1 + d2)) # sqrt(2) missing ?
362
362
 
@@ -685,7 +685,7 @@ class FullFieldReconstructor:
685
685
  # Prevent issue when out_dir is empty, which happens only if dataset/location is a relative path.
686
686
  # TODO this should be prevented earlier
687
687
  if out_dir is None or len(out_dir.strip()) == 0:
688
- out_dir = dirname(dirname(self.results[list(self.results.keys())[0]]))
688
+ out_dir = dirname(dirname(self.results[first_generator_item(self.results.keys())]))
689
689
  #
690
690
  if output_file is None:
691
691
  output_file = join(out_dir, prefix + out_cfg["file_prefix"]) + ".hdf5"
@@ -766,7 +766,8 @@ class FullFieldReconstructor:
766
766
  out_cfg = self.process_config.nabu_config["output"]
767
767
  if output_file is None:
768
768
  output_file = (
769
- join(dirname(list(self._histograms.values())[0]), out_cfg["file_prefix"] + "_histogram") + ".hdf5"
769
+ join(dirname(first_generator_item(self._histograms.values())), out_cfg["file_prefix"] + "_histogram")
770
+ + ".hdf5"
770
771
  )
771
772
  local_files = self.get_relative_files(files=list(self._histograms.values()))
772
773
  #
@@ -818,7 +819,7 @@ class FullFieldReconstructor:
818
819
  def merge_data_dumps(self, axis=1):
819
820
  # Collect in a dict where keys are step names (instead of task keys)
820
821
  dumps = {}
821
- for task_key, data_dumps in self._data_dumps.items():
822
+ for task_key, data_dumps in self._data_dumps.items(): # noqa: PERF102
822
823
  for step_name, fname in data_dumps.items():
823
824
  fname = join(basename(dirname(fname)), basename(fname))
824
825
  if step_name not in dumps:
@@ -1,4 +1,4 @@
1
- from ..fullfield.dataset_validator import *
1
+ from ..fullfield.dataset_validator import FullFieldDatasetValidator
2
2
  from ...utils import copy_dict_items
3
3
 
4
4
 
@@ -10,10 +10,9 @@ class HelicalDatasetValidator(FullFieldDatasetValidator):
10
10
 
11
11
  def _check_slice_indices(self):
12
12
  """Slice indices can be far beyond what fullfield pipeline accepts, no check here, but
13
- Nabu expects that rec_region is initialised here"""
13
+ Nabu expects that rec_region is initialised here
14
+ """
14
15
 
15
16
  what = ["start_x", "end_x", "start_y", "end_y", "start_z", "end_z"]
16
17
 
17
18
  self.rec_region = copy_dict_items(self.rec_params, what)
18
-
19
- return
@@ -1,6 +1,6 @@
1
- from ...reconstruction.fbp import *
1
+ import numpy as np
2
+ from ...reconstruction.fbp import Backprojector
2
3
  from .filtering import HelicalSinoFilter
3
- from ...utils import convert_index
4
4
 
5
5
 
6
6
  class BackprojectorHelical(Backprojector):
@@ -25,9 +25,9 @@ class BackprojectorHelical(Backprojector):
25
25
 
26
26
  def set_custom_angles_and_axis_corrections(self, angles_rad, x_per_proj):
27
27
  """To arbitrarily change angles
28
- Parameters
29
- ==========
30
28
 
29
+ Parameters
30
+ ----------
31
31
  angles_rad: array of floats
32
32
  one angle per each projection in radians
33
33
 
@@ -68,26 +68,26 @@ class HelicalSinoFilter(CudaSinoFilter):
68
68
  "padding",
69
69
  filename=get_cuda_srcfile("helical_padding.cu"),
70
70
  signature="PPfiiiii",
71
- options=[str("-DMIRROR_EDGES")],
71
+ options=["-DMIRROR_EDGES"],
72
72
  )
73
73
  self._pad_mirror_constant_kernel = self.cuda.kernel(
74
74
  "padding",
75
75
  filename=get_cuda_srcfile("helical_padding.cu"),
76
76
  signature="PPfiiiiiff",
77
- options=[str("-DMIRROR_CONSTANT")],
77
+ options=["-DMIRROR_CONSTANT"],
78
78
  )
79
79
 
80
80
  self._pad_mirror_edges_variable_rot_pos_kernel = self.cuda.kernel(
81
81
  "padding",
82
82
  filename=get_cuda_srcfile("helical_padding.cu"),
83
83
  signature="PPPiiiii",
84
- options=[str("-DMIRROR_EDGES_VARIABLE_ROT_POS")],
84
+ options=["-DMIRROR_EDGES_VARIABLE_ROT_POS"],
85
85
  )
86
86
  self._pad_mirror_constant_variable_rot_pos_kernel = self.cuda.kernel(
87
87
  "padding",
88
88
  filename=get_cuda_srcfile("helical_padding.cu"),
89
89
  signature="PPPiiiiiff",
90
- options=[str("-DMIRROR_CONSTANT_VARIABLE_ROT_POS")],
90
+ options=["-DMIRROR_CONSTANT_VARIABLE_ROT_POS"],
91
91
  )
92
92
 
93
93
  self.d_mirror_indexes = self.cuda.allocate_array(
@@ -179,6 +179,7 @@ class HelicalSinoFilter(CudaSinoFilter):
179
179
  """
180
180
  Perform the sinogram siltering.
181
181
  redefined here to use also mirror data
182
+
182
183
  Parameters
183
184
  ----------
184
185
  sino: numpy.ndarray or pycuda.gpuarray.GPUArray
@@ -29,8 +29,7 @@ class GriddedAccumulator:
29
29
  This class creates, for a selected volume slab, a standard set of radios from an helical dataset.
30
30
 
31
31
  Parameters
32
- ==========
33
-
32
+ ----------
34
33
  gridded_radios : 3D np.array
35
34
  this is the stack of new radios which will be resynthetised, by this class,
36
35
  for a selected slab.
@@ -97,7 +96,7 @@ class GriddedAccumulator:
97
96
  self.flats_srcurrent = flats_srcurrent
98
97
 
99
98
  self.flat_indexes = flat_indexes
100
- self.flat_indexes_reverse_map = dict(
99
+ self.flat_indexes_reverse_map = dict( # noqa: C404
101
100
  [(global_index, local_index) for (local_index, global_index) in enumerate(flat_indexes)]
102
101
  )
103
102
  self.flats = flats
@@ -121,7 +120,7 @@ class GriddedAccumulator:
121
120
  the accumulators are ready.
122
121
 
123
122
  Parameters
124
- ==========
123
+ ----------
125
124
  subchunk_slice: an object of the python class "slice"
126
125
  this slice slices the angular domain which corresponds to the useful
127
126
  projections which are useful for the chunk, and whose informations
@@ -278,7 +277,7 @@ class GriddedAccumulator:
278
277
  i_diag_list = [(i0 - 1) // 2, (i0 - 1) // 2 + len(self.diagnostic_searched_angles_rad_clipped)]
279
278
  for i_redundancy, i_diag in enumerate(i_diag_list):
280
279
  # print("IRED ", i_redundancy)
281
- if i_redundancy:
280
+ if i_redundancy: # noqa: SIM102
282
281
  # to avoid, in z_stages with >360 range for one single stage, to fill the second items which should instead be filled by another stage.
283
282
  if abs(original_zpix_transl - self.diagnostic_zpix_transl[i_diag_list[0]]) < 2.0:
284
283
  # print( " >>>>>> stesso z" , i_redundancy )
@@ -306,7 +305,7 @@ class GriddedAccumulator:
306
305
  self.diagnostic_radios[i_diag] += data_token * factor
307
306
  self.diagnostic_weights[i_diag] += weight * factor
308
307
  break
309
- else:
308
+ else: # noqa: RET508
310
309
  pass
311
310
 
312
311
  class _ReframingInfos:
@@ -483,8 +482,8 @@ def overlap_logic(subr_start_z, subr_end_z, dtasrc_start_z, dtasrc_end_z):
483
482
 
484
483
  def padding_logic(subr_start_z, subr_end_z, dtasrc_start_z, dtasrc_end_z):
485
484
  """.......... and the missing ranges which possibly could be obtained by extension padding"""
486
- t_h = subr_end_z - subr_start_z
487
- s_h = dtasrc_end_z - dtasrc_start_z
485
+ # t_h = subr_end_z - subr_start_z
486
+ # s_h = dtasrc_end_z - dtasrc_start_z
488
487
 
489
488
  if dtasrc_start_z <= subr_start_z:
490
489
  target_lower_padding = None
@@ -503,9 +502,9 @@ def get_reconstruction_space(span_info, min_scanwise_z, end_scanwise_z, phase_ma
503
502
  """Utility function, so far used only by the unit test, which, given the span_info object, creates the auxiliary collection arrays
504
503
  and initialises the my_z_min, my_z_end variable keeping into account the scan direction
505
504
  and the min_scanwise_z, end_scanwise_z input arguments
506
- Parameters
507
- ==========
508
505
 
506
+ Parameters
507
+ ----------
509
508
  span_info: SpanStrategy
510
509
 
511
510
  min_scanwise_z: int
@@ -1,3 +1,4 @@
1
+ # ruff: noqa
1
2
  # pylint: skip-file
2
3
 
3
4
  from os import path
@@ -3,6 +3,8 @@ from math import ceil
3
3
  from time import time
4
4
  import numpy as np
5
5
  import copy
6
+
7
+ from nabu.utils import first_generator_item
6
8
  from ...resources.logger import LoggerOrPrint
7
9
  from ...io.writer import merge_hdf5_files
8
10
  from ...cuda.utils import collect_cuda_gpus
@@ -18,7 +20,7 @@ except:
18
20
 
19
21
  from .helical_chunked_regridded_cuda import CudaHelicalChunkedRegriddedPipeline
20
22
 
21
- from ..fullfield.reconstruction import collect_cuda_gpus, FullFieldReconstructor
23
+ from ..fullfield.reconstruction import FullFieldReconstructor
22
24
 
23
25
  avail_gpus = collect_cuda_gpus() or {}
24
26
 
@@ -53,7 +55,8 @@ class HelicalReconstructorRegridded:
53
55
  Dictionary with advanced options. Please see 'Other parameters' below
54
56
  cuda_options: dict, optional
55
57
  Dictionary with cuda options passed to `nabu.cuda.processing.CudaProcessing`
56
- Other parameters
58
+
59
+ Other Parameters
57
60
  -----------------
58
61
  Advanced options can be passed in the 'extra_options' dictionary. These can be:
59
62
 
@@ -242,9 +245,9 @@ class HelicalReconstructorRegridded:
242
245
  "reconstruction" in process_config.processing_steps
243
246
  and process_config.processing_options["reconstruction"]["enable_halftomo"]
244
247
  ):
245
- radios_and_sinos = True
248
+ radios_and_sinos = True # noqa: F841
246
249
 
247
- max_dz = process_config.dataset_info.radio_dims[1]
250
+ # max_dz = process_config.dataset_info.radio_dims[1]
248
251
  chunk_size = chunk_step
249
252
  last_good_chunk_size = chunk_size
250
253
  while True:
@@ -431,7 +434,7 @@ class HelicalReconstructorRegridded:
431
434
  angles_deg = np.rad2deg(angles_rad)
432
435
 
433
436
  redundancy_angle_deg = self.process_config.nabu_config["reconstruction"]["redundancy_angle_deg"]
434
- do_helical_half_tomo = self.process_config.nabu_config["reconstruction"]["helical_halftomo"]
437
+ # do_helical_half_tomo = self.process_config.nabu_config["reconstruction"]["helical_halftomo"]
435
438
 
436
439
  self.logger.info("Creating SpanStrategy object for helical ")
437
440
  t0 = time()
@@ -460,7 +463,7 @@ class HelicalReconstructorRegridded:
460
463
  self.logger.debug("Creating a new pipeline object")
461
464
  args = [self.process_config, task["sub_region"]]
462
465
 
463
- dz = self._get_delta_z(task)
466
+ # dz = self._get_delta_z(task)
464
467
 
465
468
  pipeline = self._pipeline_cls(
466
469
  *args,
@@ -542,7 +545,7 @@ class HelicalReconstructorRegridded:
542
545
  # Prevent issue when out_dir is empty, which happens only if dataset/location is a relative path.
543
546
  # TODO this should be prevented earlier
544
547
  if out_dir is None or len(out_dir.strip()) == 0:
545
- out_dir = dirname(dirname(self.results[list(self.results.keys())[0]]))
548
+ out_dir = dirname(dirname(self.results[first_generator_item(self.results.keys())]))
546
549
  #
547
550
  if output_file is None:
548
551
  output_file = join(out_dir, prefix + out_cfg["file_prefix"]) + ".hdf5"