Coverage for local_installation_linux/mumott/pipelines/reconstruction/discrete_directions.py: 94%
25 statements
« prev ^ index » next coverage.py v7.3.2, created at 2025-05-05 21:21 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2025-05-05 21:21 +0000
1import logging
2import sys
4import numpy as np
5from numpy.typing import NDArray
6import tqdm
7from types import SimpleNamespace
9from mumott.data_handling import DataContainer
10from mumott.methods.basis_sets import NearestNeighbor
11from mumott.pipelines.reconstruction.sirt import run_sirt
13logger = logging.getLogger(__name__)
16def run_discrete_directions(data_container: DataContainer,
17 directions: NDArray[float],
18 use_gpu: bool = False,
19 maxiter: int = 20,
20 no_tqdm: bool = False,
21 ):
22 """A reconstruction pipeline for the :term:`discrete directions <DD>` algorithm, which is
23 similar the the algorithms first descibed in [Schaff2015]_.
25 Parameters
26 ----------
27 data_container
28 The :class:`DataContainer <mumott.data_handling.DataContainer>`
29 from loading the data set of interest.
30 directions
31 A N by 3 Numpy array of unit-vectors descibing a grid covering the half unit sphere.
32 use_gpu
33 Whether to use GPU resources in computing the projections.
34 Default is ``False``. If set to ``True``, the method will use
35 :class:`SAXSProjectorCUDA <mumott.methods.projectors.SAXSProjectorCUDA>`.
36 maxiter
37 Maximum number of iterations for the gradient descent solution.
38 no_tqdm:
39 Flag whether ot not to print a progress bar for the reconstruction.
40 """
41 basis_set = NearestNeighbor(directions)
42 basis_set.integration_mode = 'midpoint'
43 output_coefficients = np.zeros((*data_container.geometry.volume_shape, len(basis_set)))
45 if no_tqdm: 45 ↛ 46line 45 didn't jump to line 46, because the condition on line 45 was never true
46 iterator = range(len(basis_set))
47 else:
48 iterator = tqdm.tqdm(range(len(basis_set)), file=sys.stdout)
50 for ii in iterator:
51 sub_geometry, data_tuple = basis_set.get_sub_geometry(ii, data_container.geometry, data_container)
53 if data_tuple is None:
54 continue
56 fake_data_container = SimpleNamespace(
57 projections=SimpleNamespace(weights=data_tuple[1][..., np.newaxis]),
58 geometry=sub_geometry,
59 weights=data_tuple[1][..., np.newaxis])
61 result = run_sirt(fake_data_container,
62 maxiter=maxiter,
63 enforce_non_negativity=True,
64 use_gpu=use_gpu,
65 use_absorbances=True,
66 absorbances=data_tuple[0][..., np.newaxis],
67 no_tqdm=True)
68 output_coefficients[..., ii] = result['result']['x'][..., 0]
70 return dict(result={'x' : output_coefficients}, basis_set=basis_set)