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.
- doc/doc_config.py +32 -0
- nabu/__init__.py +1 -1
- nabu/app/bootstrap_stitching.py +4 -2
- nabu/app/cast_volume.py +7 -13
- nabu/app/cli_configs.py +0 -5
- nabu/app/compare_volumes.py +1 -1
- nabu/app/composite_cor.py +2 -4
- nabu/app/correct_rot.py +0 -8
- nabu/app/diag_to_pix.py +5 -6
- nabu/app/diag_to_rot.py +10 -11
- nabu/app/multicor.py +1 -1
- nabu/app/parse_reconstruction_log.py +1 -0
- nabu/app/prepare_weights_double.py +1 -2
- nabu/app/reconstruct_helical.py +1 -5
- nabu/app/reduce_dark_flat.py +0 -2
- nabu/app/rotate.py +3 -1
- nabu/app/tests/test_reduce_dark_flat.py +2 -2
- nabu/app/validator.py +1 -4
- nabu/cuda/convolution.py +1 -1
- nabu/cuda/fft.py +1 -1
- nabu/cuda/medfilt.py +1 -1
- nabu/cuda/padding.py +1 -1
- nabu/cuda/src/cone.cu +19 -9
- nabu/cuda/src/hierarchical_backproj.cu +16 -0
- nabu/cuda/utils.py +2 -2
- nabu/estimation/alignment.py +17 -31
- nabu/estimation/cor.py +23 -29
- nabu/estimation/cor_sino.py +2 -8
- nabu/estimation/focus.py +4 -8
- nabu/estimation/tests/test_alignment.py +2 -0
- nabu/estimation/tests/test_tilt.py +1 -1
- nabu/estimation/tilt.py +5 -4
- nabu/io/cast_volume.py +5 -5
- nabu/io/detector_distortion.py +5 -6
- nabu/io/reader.py +3 -3
- nabu/io/reader_helical.py +5 -4
- nabu/io/tests/test_cast_volume.py +2 -2
- nabu/io/tests/test_readers.py +4 -4
- nabu/io/tests/test_writers.py +2 -2
- nabu/io/utils.py +8 -4
- nabu/io/writer.py +1 -2
- nabu/misc/fftshift.py +1 -1
- nabu/misc/fourier_filters.py +1 -1
- nabu/misc/histogram.py +1 -1
- nabu/misc/histogram_cuda.py +1 -1
- nabu/misc/padding_base.py +1 -1
- nabu/misc/rotation.py +1 -1
- nabu/misc/rotation_cuda.py +1 -1
- nabu/misc/tests/test_binning.py +1 -1
- nabu/misc/transpose.py +1 -1
- nabu/misc/unsharp.py +1 -1
- nabu/misc/unsharp_cuda.py +1 -1
- nabu/misc/unsharp_opencl.py +1 -1
- nabu/misc/utils.py +1 -1
- nabu/opencl/fft.py +1 -1
- nabu/opencl/padding.py +1 -1
- nabu/opencl/utils.py +8 -8
- nabu/pipeline/config.py +2 -2
- nabu/pipeline/config_validators.py +4 -3
- nabu/pipeline/datadump.py +3 -3
- nabu/pipeline/estimators.py +6 -6
- nabu/pipeline/fullfield/chunked.py +4 -5
- nabu/pipeline/fullfield/dataset_validator.py +0 -1
- nabu/pipeline/fullfield/nabu_config.py +2 -1
- nabu/pipeline/fullfield/reconstruction.py +9 -8
- nabu/pipeline/helical/dataset_validator.py +3 -4
- nabu/pipeline/helical/fbp.py +4 -4
- nabu/pipeline/helical/filtering.py +5 -4
- nabu/pipeline/helical/gridded_accumulator.py +9 -10
- nabu/pipeline/helical/helical_chunked_regridded.py +1 -0
- nabu/pipeline/helical/helical_reconstruction.py +10 -7
- nabu/pipeline/helical/helical_utils.py +1 -2
- nabu/pipeline/helical/nabu_config.py +1 -0
- nabu/pipeline/helical/span_strategy.py +1 -0
- nabu/pipeline/helical/weight_balancer.py +1 -2
- nabu/pipeline/tests/__init__.py +0 -0
- nabu/pipeline/utils.py +1 -1
- nabu/pipeline/writer.py +1 -1
- nabu/preproc/alignment.py +0 -10
- nabu/preproc/ctf.py +8 -8
- nabu/preproc/ctf_cuda.py +1 -1
- nabu/preproc/double_flatfield_cuda.py +2 -2
- nabu/preproc/double_flatfield_variable_region.py +0 -1
- nabu/preproc/flatfield.py +1 -1
- nabu/preproc/flatfield_cuda.py +1 -2
- nabu/preproc/flatfield_variable_region.py +3 -3
- nabu/preproc/phase.py +2 -4
- nabu/preproc/phase_cuda.py +2 -2
- nabu/preproc/shift_cuda.py +0 -1
- nabu/preproc/tests/test_ctf.py +3 -3
- nabu/preproc/tests/test_double_flatfield.py +1 -1
- nabu/preproc/tests/test_flatfield.py +1 -1
- nabu/preproc/tests/test_vshift.py +4 -1
- nabu/processing/azim.py +2 -2
- nabu/processing/convolution_cuda.py +6 -4
- nabu/processing/fft_base.py +1 -1
- nabu/processing/fft_cuda.py +19 -8
- nabu/processing/fft_opencl.py +9 -4
- nabu/processing/fftshift.py +1 -1
- nabu/processing/histogram.py +1 -1
- nabu/processing/muladd.py +0 -1
- nabu/processing/padding_base.py +1 -1
- nabu/processing/padding_cuda.py +0 -1
- nabu/processing/processing_base.py +1 -1
- nabu/processing/tests/test_fft.py +1 -1
- nabu/processing/tests/test_fftshift.py +1 -1
- nabu/processing/tests/test_medfilt.py +1 -3
- nabu/processing/tests/test_padding.py +1 -1
- nabu/processing/tests/test_roll.py +1 -1
- nabu/processing/unsharp_opencl.py +1 -1
- nabu/reconstruction/astra.py +245 -0
- nabu/reconstruction/cone.py +9 -4
- nabu/reconstruction/fbp_base.py +2 -2
- nabu/reconstruction/filtering_cuda.py +1 -1
- nabu/reconstruction/hbp.py +16 -3
- nabu/reconstruction/mlem.py +0 -1
- nabu/reconstruction/projection.py +3 -5
- nabu/reconstruction/sinogram.py +1 -1
- nabu/reconstruction/sinogram_cuda.py +0 -1
- nabu/reconstruction/tests/test_cone.py +76 -3
- nabu/reconstruction/tests/test_deringer.py +2 -2
- nabu/reconstruction/tests/test_fbp.py +1 -1
- nabu/reconstruction/tests/test_halftomo.py +27 -1
- nabu/reconstruction/tests/test_mlem.py +3 -2
- nabu/reconstruction/tests/test_projector.py +7 -2
- nabu/reconstruction/tests/test_sino_normalization.py +0 -1
- nabu/resources/dataset_analyzer.py +4 -4
- nabu/resources/gpu.py +4 -4
- nabu/resources/logger.py +4 -4
- nabu/resources/nxflatfield.py +2 -2
- nabu/resources/tests/test_nxflatfield.py +4 -4
- nabu/stitching/alignment.py +1 -4
- nabu/stitching/config.py +19 -16
- nabu/stitching/frame_composition.py +8 -10
- nabu/stitching/overlap.py +2 -2
- nabu/stitching/slurm_utils.py +2 -2
- nabu/stitching/stitcher/base.py +2 -0
- nabu/stitching/stitcher/dumper/base.py +0 -1
- nabu/stitching/stitcher/dumper/postprocessing.py +1 -1
- nabu/stitching/stitcher/post_processing.py +6 -6
- nabu/stitching/stitcher/pre_processing.py +13 -11
- nabu/stitching/stitcher/single_axis.py +3 -4
- nabu/stitching/stitcher_2D.py +2 -1
- nabu/stitching/tests/test_config.py +7 -8
- nabu/stitching/tests/test_sample_normalization.py +1 -1
- nabu/stitching/tests/test_slurm_utils.py +1 -2
- nabu/stitching/tests/test_z_postprocessing_stitching.py +1 -1
- nabu/stitching/tests/test_z_preprocessing_stitching.py +4 -4
- nabu/stitching/utils/tests/__init__.py +0 -0
- nabu/stitching/utils/tests/test_post-processing.py +1 -0
- nabu/stitching/utils/utils.py +10 -12
- nabu/tests.py +0 -3
- nabu/testutils.py +30 -8
- nabu/utils.py +28 -18
- {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/METADATA +25 -25
- nabu-2025.1.0.dev4.dist-info/RECORD +320 -0
- {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/WHEEL +1 -1
- nabu/io/tests/test_detector_distortion.py +0 -178
- nabu/resources/tests/test_extract.py +0 -9
- nabu-2024.2.4.dist-info/RECORD +0 -318
- /nabu/{stitching → app}/tests/__init__.py +0 -0
- {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/LICENSE +0 -0
- {nabu-2024.2.4.dist-info → nabu-2025.1.0.dev4.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
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
nabu/misc/fourier_filters.py
CHANGED
nabu/misc/histogram.py
CHANGED
nabu/misc/histogram_cuda.py
CHANGED
nabu/misc/padding_base.py
CHANGED
nabu/misc/rotation.py
CHANGED
nabu/misc/rotation_cuda.py
CHANGED
nabu/misc/tests/test_binning.py
CHANGED
nabu/misc/transpose.py
CHANGED
nabu/misc/unsharp.py
CHANGED
nabu/misc/unsharp_cuda.py
CHANGED
nabu/misc/unsharp_opencl.py
CHANGED
nabu/misc/utils.py
CHANGED
nabu/opencl/fft.py
CHANGED
nabu/opencl/padding.py
CHANGED
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
|
-
|
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
|
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 =
|
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[
|
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
|
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
|
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
|
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
|
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
|
|
nabu/pipeline/estimators.py
CHANGED
@@ -298,7 +298,7 @@ class SinoCORFinder(CORFinderBase):
|
|
298
298
|
"""
|
299
299
|
Initialize a SinoCORFinder object.
|
300
300
|
|
301
|
-
Other
|
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, #
|
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
|
-
|
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(
|
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(
|
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
|
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
|
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"],
|
@@ -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
|
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 =
|
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[
|
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(
|
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
|
nabu/pipeline/helical/fbp.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
|
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=[
|
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=[
|
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=[
|
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=[
|
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
|
@@ -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
|
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
|
-
|
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[
|
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"
|