nabu 2025.1.0rc3__py3-none-any.whl → 2025.1.0rc5__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 ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python
2
+
3
+ from nabu.resources.nabu_config import nabu_config
4
+
5
+
6
+ def generate(file_):
7
+ def write(content):
8
+ print(content, file=file_)
9
+ for section, values in nabu_config.items():
10
+ if section == "about":
11
+ continue
12
+ write("## %s\n" % section)
13
+ for key, val in values.items():
14
+ if val["type"] == "unsupported":
15
+ continue
16
+ write(val["help"] + "\n")
17
+ write(
18
+ "```ini\n%s = %s\n```"
19
+ % (key, val["default"])
20
+ )
21
+
22
+
23
+
24
+ if __name__ == "__main__":
25
+
26
+ import sys, os
27
+ print(os.path.abspath(__file__))
28
+ exit(0)
29
+
30
+ fname = "/tmp/test.md"
31
+ with open(fname, "w") as f:
32
+ generate(f)
nabu/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "2025.1.0-rc3"
1
+ __version__ = "2025.1.0-rc5"
2
2
  __nabu_modules__ = [
3
3
  "app",
4
4
  "cuda",
nabu/app/cli_configs.py CHANGED
@@ -353,6 +353,11 @@ EstimateMotionConfig = {
353
353
  "default": 2,
354
354
  "type": int,
355
355
  },
356
+ "win_size": {
357
+ "help": "Size of the look-up window for half-tomography",
358
+ "default": 300,
359
+ "type": int,
360
+ },
356
361
  "verbose": {
357
362
  "help": "Whether to plot the movement estimation fit",
358
363
  "default": 1,
@@ -365,6 +370,16 @@ EstimateMotionConfig = {
365
370
  "help": "Whether to only generate motion file for horizontal or vertical movement: --only horizontal or --only vertical",
366
371
  "default": "",
367
372
  },
373
+ "ccd_filter_size": {
374
+ "help": "Size of conditional median filter to apply on radios. Default is zero (disabled)",
375
+ "default": 0,
376
+ "type": int,
377
+ },
378
+ "ccd_filter_threshold": {
379
+ "help": "Threshold for median filter, 'ccd_filter_size' is not zero. Default is 0.04",
380
+ "default": 0.04,
381
+ "type": float,
382
+ },
368
383
  }
369
384
 
370
385
  # Default configuration for "stitching" command
@@ -1,8 +1,11 @@
1
1
  from os import path
2
+ from multiprocessing.pool import ThreadPool
2
3
 
4
+ from ..utils import get_num_threads
3
5
  from ..resources.nxflatfield import update_dataset_info_flats_darks
4
6
  from ..resources.logger import LoggerOrPrint
5
7
  from ..resources.dataset_analyzer import analyze_dataset
8
+ from ..preproc.ccd import CCDFilter
6
9
  from ..pipeline.config_validators import convert_to_bool
7
10
  from ..pipeline.estimators import TranslationsEstimator
8
11
  from .utils import parse_params_values
@@ -26,6 +29,22 @@ def estimate_motion():
26
29
  if do_ff:
27
30
  update_dataset_info_flats_darks(dataset_info, True, loading_mode="load_if_present")
28
31
 
32
+ radios_filter = None
33
+ do_ccd_filter = args["ccd_filter_size"] > 0
34
+ if do_ccd_filter:
35
+ radios_filter_obj = CCDFilter(
36
+ dataset_info.radio_dims[::-1],
37
+ kernel_size=args["ccd_filter_size"],
38
+ median_clip_thresh=args["ccd_filter_threshold"],
39
+ )
40
+
41
+ def radios_filter(images):
42
+ def _apply_median_clip(img):
43
+ radios_filter_obj.median_clip_correction(img, output=img)
44
+
45
+ with ThreadPool(get_num_threads()) as tp:
46
+ tp.map(_apply_median_clip, images)
47
+
29
48
  est = TranslationsEstimator(
30
49
  dataset_info,
31
50
  do_flatfield=do_ff,
@@ -34,6 +53,8 @@ def estimate_motion():
34
53
  deg_xy=args["deg_xy"],
35
54
  deg_z=args["deg_z"],
36
55
  shifts_estimator="phase_cross_correlation",
56
+ radios_filter=radios_filter,
57
+ extra_options={"window_size": args["win_size"]},
37
58
  )
38
59
 
39
60
  estimated_shifts_h, estimated_shifts_v, cor = est.estimate_motion()
@@ -1000,7 +1000,7 @@ def estimate_translations(dataset_info, do_flatfield=True): ...
1000
1000
  class TranslationsEstimator:
1001
1001
 
1002
1002
  _default_extra_options = {
1003
- "window_size": 200,
1003
+ "window_size": 300,
1004
1004
  }
1005
1005
 
1006
1006
  def __init__(
@@ -1013,6 +1013,7 @@ class TranslationsEstimator:
1013
1013
  deg_xy=2,
1014
1014
  deg_z=2,
1015
1015
  shifts_estimator="phase_cross_correlation",
1016
+ radios_filter=None,
1016
1017
  extra_options=None,
1017
1018
  ):
1018
1019
  self._configure_extra_options(extra_options)
@@ -1021,6 +1022,7 @@ class TranslationsEstimator:
1021
1022
  self.angular_subsampling = angular_subsampling
1022
1023
  self.do_360 = self.dataset_info.is_360
1023
1024
  self.do_flatfield = do_flatfield
1025
+ self.radios_filter = radios_filter
1024
1026
  self.radios = None
1025
1027
  self._deg_xy = deg_xy
1026
1028
  self._deg_z = deg_z
@@ -1163,6 +1165,9 @@ class TranslationsEstimator:
1163
1165
  def estimate_motion(self):
1164
1166
  self._load_data()
1165
1167
  self._apply_flatfield()
1168
+ if self.radios_filter is not None:
1169
+ self.logger.debug("[MotionEstimation] applying radios filter")
1170
+ self.radios_filter(self.radios)
1166
1171
 
1167
1172
  n_projs_tot = self.dataset_info.n_angles
1168
1173
  if self.do_360:
@@ -1210,7 +1215,7 @@ class TranslationsEstimator:
1210
1215
  self.sample_shifts_z = estimated_shifts_v
1211
1216
  if self._cor is None:
1212
1217
  self.logger.info(
1213
- "[MotionEstimation] Estimated center of rotation (relative to middle of detector): %.2f" % cor
1218
+ "[MotionEstimation] Estimated center of rotation (relative to left-most pixel): %.2f" % cor
1214
1219
  )
1215
1220
  return estimated_shifts_h, estimated_shifts_v, cor
1216
1221
 
nabu/processing/azim.py CHANGED
@@ -96,8 +96,11 @@ def do_radial_distribution(ip, X0, Y0, mR, nBins=None, use_calibration=False, ca
96
96
  Accumulator = np.zeros((2, nBins))
97
97
 
98
98
  # Define the bounding box
99
- xmin, xmax = X0 - mR, X0 + mR
100
- ymin, ymax = Y0 - mR, Y0 + mR
99
+ height, width = ip.shape
100
+ xmin = max(int(X0 - mR), 0)
101
+ xmax = min(int(X0 + mR), width)
102
+ ymin = max(int(Y0 - mR), 0)
103
+ ymax = min(int(Y0 + mR), height)
101
104
 
102
105
  # Create grid of coordinates
103
106
  x = np.arange(xmin, xmax)
@@ -112,10 +115,11 @@ def do_radial_distribution(ip, X0, Y0, mR, nBins=None, use_calibration=False, ca
112
115
  bins = np.clip(bins - 1, 0, nBins - 1) # Adjust bins to be in range [0, nBins-1]
113
116
 
114
117
  # Accumulate values
118
+ sub_image = ip[xmin:xmax, ymin:ymax] # prevent issue on non-square images
115
119
  for b in range(nBins):
116
120
  mask = bins == b
117
121
  Accumulator[0, b] = np.sum(mask)
118
- Accumulator[1, b] = np.sum(ip[mask])
122
+ Accumulator[1, b] = np.sum(sub_image[mask])
119
123
 
120
124
  # Normalize integrated intensity
121
125
  Accumulator[1] /= Accumulator[0]
@@ -0,0 +1,245 @@
1
+ # ruff: noqa
2
+ try:
3
+ import astra
4
+
5
+ __have_astra__ = True
6
+ except ImportError:
7
+ __have_astra__ = False
8
+ astra = None
9
+
10
+
11
+ class AstraReconstructor:
12
+ """
13
+ Base class for reconstructors based on the Astra toolbox
14
+ """
15
+
16
+ default_extra_options = {
17
+ "axis_correction": None,
18
+ "clip_outer_circle": False,
19
+ "scale_factor": None,
20
+ "filter_cutoff": 1.0,
21
+ "outer_circle_value": 0.0,
22
+ }
23
+
24
+ def __init__(
25
+ self,
26
+ sinos_shape,
27
+ angles=None,
28
+ volume_shape=None,
29
+ rot_center=None,
30
+ pixel_size=None,
31
+ padding_mode="zeros",
32
+ filter_name=None,
33
+ slice_roi=None,
34
+ cuda_options=None,
35
+ extra_options=None,
36
+ ):
37
+ self._configure_extra_options(extra_options)
38
+ self._init_cuda(cuda_options)
39
+ self._set_sino_shape(sinos_shape)
40
+ self._orig_prog_geom = None
41
+ self._init_geometry(
42
+ source_origin_dist,
43
+ origin_detector_dist,
44
+ pixel_size,
45
+ angles,
46
+ volume_shape,
47
+ rot_center,
48
+ relative_z_position,
49
+ slice_roi,
50
+ )
51
+ self._init_fdk(padding_mode, filter_name)
52
+ self._alg_id = None
53
+ self._vol_id = None
54
+ self._proj_id = None
55
+
56
+ def _configure_extra_options(self, extra_options):
57
+ self.extra_options = self.default_extra_options.copy()
58
+ self.extra_options.update(extra_options or {})
59
+
60
+ def _init_cuda(self, cuda_options):
61
+ cuda_options = cuda_options or {}
62
+ self.cuda = CudaProcessing(**cuda_options)
63
+
64
+ def _set_sino_shape(self, sinos_shape):
65
+ if len(sinos_shape) != 3:
66
+ raise ValueError("Expected a 3D shape")
67
+ self.sinos_shape = sinos_shape
68
+ self.n_sinos, self.n_angles, self.prj_width = sinos_shape
69
+
70
+ def _set_pixel_size(self, pixel_size):
71
+ if pixel_size is None:
72
+ det_spacing_y = det_spacing_x = 1
73
+ elif np.iterable(pixel_size):
74
+ det_spacing_y, det_spacing_x = pixel_size
75
+ else:
76
+ # assuming scalar
77
+ det_spacing_y = det_spacing_x = pixel_size
78
+ self._det_spacing_y = det_spacing_y
79
+ self._det_spacing_x = det_spacing_x
80
+
81
+ def _set_slice_roi(self, slice_roi):
82
+ self.slice_roi = slice_roi
83
+ self._vol_geom_n_x = self.n_x
84
+ self._vol_geom_n_y = self.n_y
85
+ self._crop_data = True
86
+ if slice_roi is None:
87
+ return
88
+ start_x, end_x, start_y, end_y = slice_roi
89
+ if roi_is_centered(self.volume_shape[1:], (slice(start_y, end_y), slice(start_x, end_x))):
90
+ # Astra can only reconstruct subregion centered around the origin
91
+ self._vol_geom_n_x = self.n_x - start_x * 2
92
+ self._vol_geom_n_y = self.n_y - start_y * 2
93
+ else:
94
+ raise NotImplementedError(
95
+ "Astra supports only slice_roi centered around origin (got slice_roi=%s with n_x=%d, n_y=%d)"
96
+ % (str(slice_roi), self.n_x, self.n_y)
97
+ )
98
+
99
+ def _init_geometry(
100
+ self,
101
+ source_origin_dist,
102
+ origin_detector_dist,
103
+ pixel_size,
104
+ angles,
105
+ volume_shape,
106
+ rot_center,
107
+ relative_z_position,
108
+ slice_roi,
109
+ ):
110
+ if angles is None:
111
+ self.angles = np.linspace(0, 2 * np.pi, self.n_angles, endpoint=True)
112
+ else:
113
+ self.angles = angles
114
+ if volume_shape is None:
115
+ volume_shape = (self.sinos_shape[0], self.sinos_shape[2], self.sinos_shape[2])
116
+ self.volume_shape = volume_shape
117
+ self.n_z, self.n_y, self.n_x = self.volume_shape
118
+ self.source_origin_dist = source_origin_dist
119
+ self.origin_detector_dist = origin_detector_dist
120
+ self.magnification = 1 + origin_detector_dist / source_origin_dist
121
+ self._set_slice_roi(slice_roi)
122
+ self.vol_geom = astra.create_vol_geom(self._vol_geom_n_y, self._vol_geom_n_x, self.n_z)
123
+ self.vol_shape = astra.geom_size(self.vol_geom)
124
+ self._cor_shift = 0.0
125
+ self.rot_center = rot_center
126
+ if rot_center is not None:
127
+ self._cor_shift = (self.sinos_shape[-1] - 1) / 2.0 - rot_center
128
+ self._set_pixel_size(pixel_size)
129
+ self._axis_corrections = self.extra_options.get("axis_correction", None)
130
+ self._create_astra_proj_geometry(relative_z_position)
131
+
132
+ def _create_astra_proj_geometry(self, relative_z_position):
133
+ # This object has to be re-created each time, because once the modifications below are done,
134
+ # it is no more a "cone" geometry but a "cone_vec" geometry, and cannot be updated subsequently
135
+ # (see astra/functions.py:271)
136
+ self.proj_geom = astra.create_proj_geom(
137
+ "cone",
138
+ self._det_spacing_x,
139
+ self._det_spacing_y,
140
+ self.n_sinos,
141
+ self.prj_width,
142
+ self.angles,
143
+ self.source_origin_dist,
144
+ self.origin_detector_dist,
145
+ )
146
+ self.relative_z_position = relative_z_position or 0.0
147
+ # This will turn the geometry of type "cone" into a geometry of type "cone_vec"
148
+ if self._orig_prog_geom is None:
149
+ self._orig_prog_geom = self.proj_geom
150
+ self.proj_geom = astra.geom_postalignment(self.proj_geom, (self._cor_shift, 0))
151
+ # (src, detector_center, u, v) = (srcX, srcY, srcZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ)
152
+ vecs = self.proj_geom["Vectors"]
153
+
154
+ # To adapt the center of rotation:
155
+ # dX = cor_shift * cos(theta) - origin_detector_dist * sin(theta)
156
+ # dY = origin_detector_dist * cos(theta) + cor_shift * sin(theta)
157
+ if self._axis_corrections is not None:
158
+ # should we check that dX and dY match the above formulas ?
159
+ cor_shifts = self._cor_shift + self._axis_corrections
160
+ vecs[:, 3] = cor_shifts * np.cos(self.angles) - self.origin_detector_dist * np.sin(self.angles)
161
+ vecs[:, 4] = self.origin_detector_dist * np.cos(self.angles) + cor_shifts * np.sin(self.angles)
162
+
163
+ # To adapt the z position:
164
+ # Component 2 of vecs is the z coordinate of the source, component 5 is the z component of the detector position
165
+ # We need to re-create the same inclination of the cone beam, thus we need to keep the inclination of the two z positions.
166
+ # The detector is centered on the rotation axis, thus moving it up or down, just moves it out of the reconstruction volume.
167
+ # We can bring back the detector in the correct volume position, by applying a rigid translation of both the detector and the source.
168
+ # The translation is exactly the amount that brought the detector up or down, but in the opposite direction.
169
+ vecs[:, 2] = -self.relative_z_position
170
+
171
+ def _set_output(self, volume):
172
+ if volume is not None:
173
+ expected_shape = self.vol_shape # if not (self._crop_data) else self._output_cropped_shape
174
+ self.cuda.check_array(volume, expected_shape)
175
+ self.cuda.set_array("output", volume)
176
+ if volume is None:
177
+ self.cuda.allocate_array("output", self.vol_shape)
178
+ d_volume = self.cuda.get_array("output")
179
+ z, y, x = d_volume.shape
180
+ self._vol_link = astra.data3d.GPULink(d_volume.ptr, x, y, z, d_volume.strides[-2])
181
+ self._vol_id = astra.data3d.link("-vol", self.vol_geom, self._vol_link)
182
+
183
+ def _set_input(self, sinos):
184
+ self.cuda.check_array(sinos, self.sinos_shape)
185
+ self.cuda.set_array("sinos", sinos) # self.cuda.sinos is now a GPU array
186
+ # TODO don't create new link/proj_id if ptr is the same ?
187
+ # But it seems Astra modifies the input sinogram while doing FDK, so this might be not relevant
188
+ d_sinos = self.cuda.get_array("sinos")
189
+
190
+ # self._proj_data_link = astra.data3d.GPULink(d_sinos.ptr, self.prj_width, self.n_angles, self.n_z, sinos.strides[-2])
191
+ self._proj_data_link = astra.data3d.GPULink(
192
+ d_sinos.ptr, self.prj_width, self.n_angles, self.n_sinos, d_sinos.strides[-2]
193
+ )
194
+ self._proj_id = astra.data3d.link("-sino", self.proj_geom, self._proj_data_link)
195
+
196
+ def _preprocess_data(self):
197
+ d_sinos = self.cuda.sinos
198
+ for i in range(d_sinos.shape[0]):
199
+ self.sino_filter.filter_sino(d_sinos[i], output=d_sinos[i])
200
+
201
+ def _update_reconstruction(self):
202
+ cfg = astra.astra_dict("BP3D_CUDA")
203
+ cfg["ReconstructionDataId"] = self._vol_id
204
+ cfg["ProjectionDataId"] = self._proj_id
205
+ if self._alg_id is not None:
206
+ astra.algorithm.delete(self._alg_id)
207
+ self._alg_id = astra.algorithm.create(cfg)
208
+
209
+ def reconstruct(self, sinos, output=None, relative_z_position=None):
210
+ """
211
+ sinos: numpy.ndarray or pycuda.gpuarray
212
+ Sinograms, with shape (n_sinograms, n_angles, width)
213
+ output: pycuda.gpuarray, optional
214
+ Output array. If not provided, a new numpy array is returned
215
+ relative_z_position: int, optional
216
+ Position of the central slice of the slab, with respect to the full stack of slices.
217
+ By default it is set to zero, meaning that the current slab is assumed in the middle of the stack
218
+ """
219
+ self._create_astra_proj_geometry(relative_z_position)
220
+ self._set_input(sinos)
221
+ self._set_output(output)
222
+ self._preprocess_data()
223
+ self._update_reconstruction()
224
+ astra.algorithm.run(self._alg_id)
225
+ #
226
+ # NB: Could also be done with
227
+ # from astra.experimental import direct_BP3D
228
+ # projector_id = astra.create_projector("cuda3d", self.proj_geom, self.vol_geom, options=None)
229
+ # direct_BP3D(projector_id, self._vol_link, self._proj_data_link)
230
+ #
231
+ result = self.cuda.get_array("output")
232
+ if output is None:
233
+ result = result.get()
234
+ if self.extra_options.get("scale_factor", None) is not None:
235
+ result *= np.float32(self.extra_options["scale_factor"]) # in-place for pycuda
236
+ self.cuda.recover_arrays_references(["sinos", "output"])
237
+ return result
238
+
239
+ def __del__(self):
240
+ if getattr(self, "_alg_id", None) is not None:
241
+ astra.algorithm.delete(self._alg_id)
242
+ if getattr(self, "_vol_id", None) is not None:
243
+ astra.data3d.delete(self._vol_id)
244
+ if getattr(self, "_proj_id", None) is not None:
245
+ astra.data3d.delete(self._proj_id)
@@ -104,7 +104,7 @@ class MLEMReconstructor:
104
104
  def reset_rot_center(self, cor):
105
105
  self.cor = -cor + (self.sinos_shape[-1] - 1) / 2.0
106
106
 
107
- def reconstruct(self, data_vwu):
107
+ def reconstruct(self, data_vwu, x0=None):
108
108
  """
109
109
  data_align_vwu: numpy.ndarray or pycuda.gpuarray
110
110
  Raw data, with shape (n_sinograms, n_angles, width)
@@ -134,5 +134,5 @@ class MLEMReconstructor:
134
134
  with cct.projectors.ProjectorUncorrected(
135
135
  self.vol_geom_align, self.angles_rad, rot_axis_shift_pix=self.cor, prj_geom=self.prj_geom_align
136
136
  ) as A:
137
- rec, _ = solver(A, data_vwu, iterations=self.n_iterations, **self.solver_opts)
137
+ rec, _ = solver(A, data_vwu, iterations=self.n_iterations, x0=x0, **self.solver_opts)
138
138
  return rec * self.scale_factor
@@ -328,8 +328,8 @@ class DatasetAnalyzer:
328
328
  Return True iff the scan is 360 degrees (regardless of half-tomo mode)
329
329
  """
330
330
  angles = self.rotation_angles
331
- d_theta = angles[1] - angles[0]
332
- return np.isclose(angles.max() - angles.min(), 2 * np.pi, atol=2 * d_theta)
331
+ delta_theta = abs(angles.max() - angles.min())
332
+ return abs(delta_theta - 2 * np.pi) < abs(delta_theta - np.pi)
333
333
 
334
334
 
335
335
  class EDFDatasetAnalyzer(DatasetAnalyzer):
@@ -71,7 +71,7 @@ def save_reduced_frames(dataset_info, reduced_frames_arrays, reduced_frames_urls
71
71
  darks_flats_dir_url = reduced_frames_urls.get("user", None)
72
72
  if darks_flats_dir_url is not None:
73
73
  output_url = darks_flats_dir_url
74
- elif is_writeable(os.path.dirname(reduced_frames_urls["dataset"]["flats"].file_path())):
74
+ elif is_writeable(os.path.abspath(os.path.dirname(reduced_frames_urls["dataset"]["flats"].file_path()))):
75
75
  output_url = reduced_frames_urls["dataset"]
76
76
  else:
77
77
  output_url = reduced_frames_urls["output"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nabu
3
- Version: 2025.1.0rc3
3
+ Version: 2025.1.0rc5
4
4
  Summary: Nabu - Tomography software
5
5
  Author-email: Pierre Paleo <pierre.paleo@esrf.fr>, Henri Payno <henri.payno@esrf.fr>, Alessandro Mirone <mirone@esrf.fr>, Jérôme Lesaint <jerome.lesaint@esrf.fr>
6
6
  Maintainer-email: Pierre Paleo <pierre.paleo@esrf.fr>
@@ -1,7 +1,8 @@
1
1
  doc/conf.py,sha256=3xtCarCHrXPr50GbeRDuH-o3Jzojw7mpr7vpGfZPLAE,3787
2
2
  doc/create_conf_doc.py,sha256=IVOdP70KvbW9WS_UQu3Iyd0YfS60E2fJ5IDtQ_s4cDw,1143
3
+ doc/doc_config.py,sha256=anqeOVjqE2e7eVzg7yuh9dvIneTkrA5doGl1cVBqT7Q,730
3
4
  doc/get_mathjax.py,sha256=VIvKRCdDuF2VoY8JD3mSey9XX13AZMmwTJBHdt1tUs4,1012
4
- nabu/__init__.py,sha256=weQJf5hGEi-BzNCLAkn3BNQ71AJRC7nINDlNmkELmCc,274
5
+ nabu/__init__.py,sha256=MqQy5o-iAgwXYvJPxuObZvQDv0dpmXSmWkMXaLkGkog,274
5
6
  nabu/tests.py,sha256=hOJD1GGxn_KE1bWMoxfjnjzI7d9JBUpoc9B2_tVFiEk,1370
6
7
  nabu/testutils.py,sha256=eL81DWgYwu2CCFmDMsFs4QjfI7w9RPXFuPU5gvYF6No,8631
7
8
  nabu/utils.py,sha256=tJI64BNXMhD6W293fwwcgf9bvTalYG_5AwVGYkgi6tU,27179
@@ -9,14 +10,14 @@ nabu/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
10
  nabu/app/bootstrap.py,sha256=3yLZJmrmQBmPJMBtE2ih2cspfqOy5T_UN2U8B3i_hkI,3266
10
11
  nabu/app/bootstrap_stitching.py,sha256=wCKgugOQr6-lPMWEn4AYQeric0tCuRc9O-RnpBuTWAA,2230
11
12
  nabu/app/cast_volume.py,sha256=OufJDx_ZJ-ZbhbvIPHxRox4jtL6PfWcL148g77BWCDU,11454
12
- nabu/app/cli_configs.py,sha256=paHLX7ZDmTKhiXF9ZDzo18ld7H1HoOpaO8YnHPAqwhc,24991
13
+ nabu/app/cli_configs.py,sha256=SakK1GhLDR4msZIJa0werjK6KxggrIED2yg6kxcDkJk,25482
13
14
  nabu/app/compare_volumes.py,sha256=3qm3QsxV-D_myLAkhM_LlX0DTrDmhzfhrnNak-1538Q,3337
14
15
  nabu/app/composite_cor.py,sha256=-qAbMJCFa0NmSb1hO2G1QvdW4fwEXSMBBbSFCnQXmCc,5068
15
16
  nabu/app/create_distortion_map_from_poly.py,sha256=aa-vE-ndB9PsuHwdHUW7-8jGz4BxvjC-bQDWHlPV0Kg,6193
16
17
  nabu/app/diag_to_pix.py,sha256=KKIj4YrcvEc8Ey-_T3yvxeSKTfrY5o13ekteMQN_cr4,14987
17
18
  nabu/app/diag_to_rot.py,sha256=tBaF1Oy0-bjCqkLFK-Bu_n74easzLlRkI_FTC1cAH2Q,16933
18
19
  nabu/app/double_flatfield.py,sha256=1yquRUIHYXmrIg7NGHMDIXpkUCS_muEioUeqLyWf8PI,5641
19
- nabu/app/estimate_motion.py,sha256=VyUv3scqbzj8mlccdMO3XgI-HIekFjxFtlVEGd2swo4,2079
20
+ nabu/app/estimate_motion.py,sha256=-E21ttzzHYSYnDnFo4ggVgIP3AARLUgU2IA4L95vz7k,2844
20
21
  nabu/app/generate_header.py,sha256=Voo-FAvwS_mU5gtDxyqpZnSpP_mlMSfd_6bEtgdi_tg,8919
21
22
  nabu/app/histogram.py,sha256=gyLXKwFrU5WPQMkM1k8OdpIXSwGEEKC-f8RcTHKOho4,7930
22
23
  nabu/app/multicor.py,sha256=FjmJurruRmrwXF7v56KlTszQGIGsqft1_P7AKR9feY0,4726
@@ -134,7 +135,7 @@ nabu/pipeline/config_validators.py,sha256=Wx9nnUpfxTJ8H2ODkUyjImTtJS9V68TafLH1Te
134
135
  nabu/pipeline/datadump.py,sha256=tKW-Dl28FU2vf1OuIie_YI1-GT1DMreis57sOR-DuGU,7026
135
136
  nabu/pipeline/dataset_validator.py,sha256=etQw9NC_YGsdWCgjsn8aJ3WfvcRuJlLVZlWoqhvvo-8,9263
136
137
  nabu/pipeline/detector_distortion_provider.py,sha256=ru1AxbcuO-FA8FYooPBWgp1lzdSDUtzFUC1A_sS8jME,920
137
- nabu/pipeline/estimators.py,sha256=8OKGEMn6VKwyy1FK1eADokP32AOolsXM8pmwc4FOs8E,51556
138
+ nabu/pipeline/estimators.py,sha256=ALzlcBxaVMt7OprEgndfBE_csuv9aKZax3erD3nBWU0,51786
138
139
  nabu/pipeline/params.py,sha256=UKMQWFQnrlNMW5aIGty-JoGmBdkS6tpoAXCjW8n6FX8,4229
139
140
  nabu/pipeline/processconfig.py,sha256=3xx2Lc8uEzPAqSMwUncr4RCiCtKn2c7wnXXbPSn8GNo,7719
140
141
  nabu/pipeline/reader.py,sha256=wkxPHYOi_C8dHNc7kddB8AMtFuW7GjsP_tm6SJeHlEY,4792
@@ -192,7 +193,7 @@ nabu/preproc/tests/test_paganin.py,sha256=Ixlp624o0xtFs12akN6sDn-gHWXm1wVlcdumm2
192
193
  nabu/preproc/tests/test_pcaflats.py,sha256=tZpMNzEtcqhLgnfl02VYyn9Ez8_YmZgtHAZublYNTHo,6356
193
194
  nabu/preproc/tests/test_vshift.py,sha256=Gq9sDtbbAAdLTJALH2qcbeYXE5dINQ8QpBnCgZM0tFQ,2972
194
195
  nabu/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
195
- nabu/processing/azim.py,sha256=GIv_C1NYjUP3IYd51qvfECTDu-rfs3Dl2Hb5-ZhdhHY,7080
196
+ nabu/processing/azim.py,sha256=edTySuOWaZlc2dxU-PSY7Odd_mrVl0_MtjOvh8fzKxw,7264
196
197
  nabu/processing/convolution_cuda.py,sha256=jOLKdEwzBwNZPTEjXIBWStZp22ieeukc6KGnuSNVnaA,15421
197
198
  nabu/processing/fft_base.py,sha256=wSLiyJEwX51chfZG3CWPl0DvKp182qAmTnRY8N1mWW0,5741
198
199
  nabu/processing/fft_cuda.py,sha256=0JNzdSPPQ1xS38mjsgriN3-Cj9MXCtADLVHzIQjQjWc,3467
@@ -227,6 +228,7 @@ nabu/processing/tests/test_rotation.py,sha256=5O1yHthJfdoP-2loXob96j_V2IwI2eb8ro
227
228
  nabu/processing/tests/test_transpose.py,sha256=hTG17wTaB5Wv6twbW3ZFhBv6BYfqJY7DTQPoO0-KdkM,2760
228
229
  nabu/processing/tests/test_unsharp.py,sha256=R3ovbwDDp3ccy2A8t6CcUVELXRWkED5EnQdN2FQOfQM,4391
229
230
  nabu/reconstruction/__init__.py,sha256=EmKVvx_-FJvzJngG4ielIC7FhMCpI1Waaflg_lF44tk,163
231
+ nabu/reconstruction/astra.py,sha256=qnFYabU-Bzgys8hXjIBcwO2NazrvhNXUYFIkMHc6BmM,10444
230
232
  nabu/reconstruction/cone.py,sha256=tSjaMDHeFV-h_IFbxUqSbhqlWmvlBcJQ8u89Y9Q9gg8,20559
231
233
  nabu/reconstruction/fbp.py,sha256=ptHcQsZTxgMFa9PhFJeTzDekibWR-P1BUj2SvRrk770,5684
232
234
  nabu/reconstruction/fbp_base.py,sha256=usd49ctQMI5w6uU5xn8qBsN7gI95iU9a3jRZgSPmOJk,18653
@@ -235,7 +237,7 @@ nabu/reconstruction/filtering.py,sha256=monJnA_kk9k_Gy7bMAos9I-XgU8czWhf9vBth6ik
235
237
  nabu/reconstruction/filtering_cuda.py,sha256=_S-BZMhtnNt8ugePSmf-LF7JvMPCOyGPUMSseymgwZw,4019
236
238
  nabu/reconstruction/filtering_opencl.py,sha256=v-sUzbnRp6M1B221F-iSh-crBCGknjHYYsjFs05VhDY,3788
237
239
  nabu/reconstruction/hbp.py,sha256=Qll7i20LWxUo1-SHRxemkYAolBTP8HScwt1OvWmD2r0,18642
238
- nabu/reconstruction/mlem.py,sha256=ToQjy81vFvRwNKc8YA8jWAa4Ms6bQSQmRBx8QcBZ_oc,5778
240
+ nabu/reconstruction/mlem.py,sha256=wgC2pKl6RKB-f2318worB9VE-qCGoQcz24aKbtkrJos,5794
239
241
  nabu/reconstruction/projection.py,sha256=SNocaOY9HuNiHs-VxkW9IS707JPJnd3sDjAbf7aIw2E,9081
240
242
  nabu/reconstruction/reconstructor.py,sha256=16xxHcK4iie-uh-trf6x_IuvgxJKBvQRTE5B8tnc4F8,7358
241
243
  nabu/reconstruction/reconstructor_cuda.py,sha256=m_3GzG44PRyiSEfTvYjgr5atLwl26hMfZOMyqTWxp0g,1644
@@ -256,10 +258,10 @@ nabu/reconstruction/tests/test_reconstructor.py,sha256=xzfEM0j48ScQoGqWVcAK74HG9
256
258
  nabu/reconstruction/tests/test_sino_normalization.py,sha256=qNnpVUp3UcFGyLlSP0rCzE5hxdV6YENL9AF6mo72WcQ,3669
257
259
  nabu/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
258
260
  nabu/resources/cor.py,sha256=-mcrTbj3G7o4PP5E_gIRo2j6_-ADmMkkOc_0CyQv84c,170
259
- nabu/resources/dataset_analyzer.py,sha256=PfYov5UrEkfE3oMLZaVJEpEWQuR5gtxctkA1hPhcpK4,23980
261
+ nabu/resources/dataset_analyzer.py,sha256=WnY3GpNc5EfmYaCSgoCM2kguBkd3LC2BRa6U1vO6wfI,23982
260
262
  nabu/resources/gpu.py,sha256=oQA8PpPdyuIzpxq1PwVd9gJdyCiLIry2godUV1AbPW0,5769
261
263
  nabu/resources/logger.py,sha256=xV9UoLZBw3wXAWYfOgqrnOtzJc9aC1VNO4LM2cHxWJg,3738
262
- nabu/resources/nxflatfield.py,sha256=uPivKr4T5AYDGeyxoLns7UL6KYZt_2niNYuSsXrUMm8,12368
264
+ nabu/resources/nxflatfield.py,sha256=kgHPf_jGQiuJ_EFe8fladRkx_PM6PfdRtcf5Tf2cYgU,12385
263
265
  nabu/resources/utils.py,sha256=79iO6I0sXx8VGXZOC9eXquNvasF37A9Zr6r2BYSwJWU,5974
264
266
  nabu/resources/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
265
267
  nabu/resources/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -317,9 +319,9 @@ nabu/thirdparty/pore3d_deringer_munch.py,sha256=o4bisnFc-wMjuohWBT8wgWmfNehPQGtC
317
319
  nabu/thirdparty/tomocupy_remove_stripe.py,sha256=Khe4zFf0kRzu65Yxnvq58gt1ljOztqJGdMDhVAiM7lM,24363
318
320
  nabu/thirdparty/tomopy_phase.py,sha256=hK4oPpkogLOhv23XzzEXQY2u3r8fJvASY_bINVs6ERE,8634
319
321
  nabu/thirdparty/tomwer_load_flats_darks.py,sha256=ZNoVAinUb_wGYbfvs_4BVnWsjsQmNxSvCh1bWhR2WWg,5611
320
- nabu-2025.1.0rc3.dist-info/licenses/LICENSE,sha256=1eAIPSnEsnSFNUODnLtNtQTs76exG3ZxJ1DJR6zoUBA,1066
321
- nabu-2025.1.0rc3.dist-info/METADATA,sha256=YmXboCie2GZY8Om4wco2-8--nuhCJnhMq99FXIYKSfE,4274
322
- nabu-2025.1.0rc3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
323
- nabu-2025.1.0rc3.dist-info/entry_points.txt,sha256=YxzCY5CNQ1XHrIGbRKg-BgC1Jy7QaCITdITpyhhxpZU,1338
324
- nabu-2025.1.0rc3.dist-info/top_level.txt,sha256=fsm_N3eXLRZk2QXF9OSKPNDPFXOz8FAQjHh5avT3dok,9
325
- nabu-2025.1.0rc3.dist-info/RECORD,,
322
+ nabu-2025.1.0rc5.dist-info/licenses/LICENSE,sha256=1eAIPSnEsnSFNUODnLtNtQTs76exG3ZxJ1DJR6zoUBA,1066
323
+ nabu-2025.1.0rc5.dist-info/METADATA,sha256=AL9rbvVgIzYBY5oxByuzL3yj8iZBJ0ozErVn3Y8n8FU,4274
324
+ nabu-2025.1.0rc5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
325
+ nabu-2025.1.0rc5.dist-info/entry_points.txt,sha256=YxzCY5CNQ1XHrIGbRKg-BgC1Jy7QaCITdITpyhhxpZU,1338
326
+ nabu-2025.1.0rc5.dist-info/top_level.txt,sha256=fsm_N3eXLRZk2QXF9OSKPNDPFXOz8FAQjHh5avT3dok,9
327
+ nabu-2025.1.0rc5.dist-info/RECORD,,