nabu 2023.2.1__py3-none-any.whl → 2024.1.0rc3__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 (183) hide show
  1. doc/conf.py +1 -1
  2. doc/doc_config.py +32 -0
  3. nabu/__init__.py +2 -1
  4. nabu/app/bootstrap_stitching.py +1 -1
  5. nabu/app/cli_configs.py +122 -2
  6. nabu/app/composite_cor.py +27 -2
  7. nabu/app/correct_rot.py +70 -0
  8. nabu/app/create_distortion_map_from_poly.py +42 -18
  9. nabu/app/diag_to_pix.py +358 -0
  10. nabu/app/diag_to_rot.py +449 -0
  11. nabu/app/generate_header.py +4 -3
  12. nabu/app/histogram.py +2 -2
  13. nabu/app/multicor.py +6 -1
  14. nabu/app/parse_reconstruction_log.py +151 -0
  15. nabu/app/prepare_weights_double.py +83 -22
  16. nabu/app/reconstruct.py +5 -1
  17. nabu/app/reconstruct_helical.py +7 -0
  18. nabu/app/reduce_dark_flat.py +6 -3
  19. nabu/app/rotate.py +4 -4
  20. nabu/app/stitching.py +16 -2
  21. nabu/app/tests/test_reduce_dark_flat.py +18 -2
  22. nabu/app/validator.py +4 -4
  23. nabu/cuda/convolution.py +8 -376
  24. nabu/cuda/fft.py +4 -0
  25. nabu/cuda/kernel.py +4 -4
  26. nabu/cuda/medfilt.py +5 -158
  27. nabu/cuda/padding.py +5 -71
  28. nabu/cuda/processing.py +23 -2
  29. nabu/cuda/src/ElementOp.cu +78 -0
  30. nabu/cuda/src/backproj.cu +28 -2
  31. nabu/cuda/src/fourier_wavelets.cu +2 -2
  32. nabu/cuda/src/normalization.cu +23 -0
  33. nabu/cuda/src/padding.cu +2 -2
  34. nabu/cuda/src/transpose.cu +16 -0
  35. nabu/cuda/utils.py +39 -0
  36. nabu/estimation/alignment.py +10 -1
  37. nabu/estimation/cor.py +808 -38
  38. nabu/estimation/cor_sino.py +7 -9
  39. nabu/estimation/tests/test_cor.py +85 -3
  40. nabu/io/reader.py +26 -18
  41. nabu/io/tests/test_cast_volume.py +3 -3
  42. nabu/io/tests/test_detector_distortion.py +3 -3
  43. nabu/io/tiffwriter_zmm.py +2 -2
  44. nabu/io/utils.py +14 -4
  45. nabu/io/writer.py +5 -3
  46. nabu/misc/fftshift.py +6 -0
  47. nabu/misc/histogram.py +5 -285
  48. nabu/misc/histogram_cuda.py +8 -104
  49. nabu/misc/kernel_base.py +3 -121
  50. nabu/misc/padding_base.py +5 -69
  51. nabu/misc/processing_base.py +3 -107
  52. nabu/misc/rotation.py +5 -62
  53. nabu/misc/rotation_cuda.py +5 -65
  54. nabu/misc/transpose.py +6 -0
  55. nabu/misc/unsharp.py +3 -78
  56. nabu/misc/unsharp_cuda.py +5 -52
  57. nabu/misc/unsharp_opencl.py +8 -85
  58. nabu/opencl/fft.py +6 -0
  59. nabu/opencl/kernel.py +21 -6
  60. nabu/opencl/padding.py +5 -72
  61. nabu/opencl/processing.py +27 -5
  62. nabu/opencl/src/backproj.cl +3 -3
  63. nabu/opencl/src/fftshift.cl +65 -12
  64. nabu/opencl/src/padding.cl +2 -2
  65. nabu/opencl/src/roll.cl +96 -0
  66. nabu/opencl/src/transpose.cl +16 -0
  67. nabu/pipeline/config_validators.py +63 -3
  68. nabu/pipeline/dataset_validator.py +2 -2
  69. nabu/pipeline/estimators.py +193 -35
  70. nabu/pipeline/fullfield/chunked.py +34 -17
  71. nabu/pipeline/fullfield/chunked_cuda.py +7 -5
  72. nabu/pipeline/fullfield/computations.py +48 -13
  73. nabu/pipeline/fullfield/nabu_config.py +13 -13
  74. nabu/pipeline/fullfield/processconfig.py +10 -5
  75. nabu/pipeline/fullfield/reconstruction.py +1 -2
  76. nabu/pipeline/helical/fbp.py +5 -0
  77. nabu/pipeline/helical/filtering.py +12 -9
  78. nabu/pipeline/helical/gridded_accumulator.py +179 -33
  79. nabu/pipeline/helical/helical_chunked_regridded.py +262 -151
  80. nabu/pipeline/helical/helical_chunked_regridded_cuda.py +4 -11
  81. nabu/pipeline/helical/helical_reconstruction.py +56 -18
  82. nabu/pipeline/helical/span_strategy.py +1 -1
  83. nabu/pipeline/helical/tests/test_accumulator.py +4 -0
  84. nabu/pipeline/params.py +23 -2
  85. nabu/pipeline/processconfig.py +3 -8
  86. nabu/pipeline/tests/test_chunk_reader.py +78 -0
  87. nabu/pipeline/tests/test_estimators.py +120 -2
  88. nabu/pipeline/utils.py +25 -0
  89. nabu/pipeline/writer.py +2 -0
  90. nabu/preproc/ccd_cuda.py +9 -7
  91. nabu/preproc/ctf.py +21 -26
  92. nabu/preproc/ctf_cuda.py +25 -25
  93. nabu/preproc/double_flatfield.py +14 -2
  94. nabu/preproc/double_flatfield_cuda.py +7 -11
  95. nabu/preproc/flatfield_cuda.py +23 -27
  96. nabu/preproc/phase.py +19 -24
  97. nabu/preproc/phase_cuda.py +21 -21
  98. nabu/preproc/shift_cuda.py +58 -28
  99. nabu/preproc/tests/test_ctf.py +5 -5
  100. nabu/preproc/tests/test_double_flatfield.py +2 -2
  101. nabu/preproc/tests/test_vshift.py +13 -2
  102. nabu/processing/__init__.py +0 -0
  103. nabu/processing/convolution_cuda.py +375 -0
  104. nabu/processing/fft_base.py +163 -0
  105. nabu/processing/fft_cuda.py +256 -0
  106. nabu/processing/fft_opencl.py +54 -0
  107. nabu/processing/fftshift.py +134 -0
  108. nabu/processing/histogram.py +286 -0
  109. nabu/processing/histogram_cuda.py +103 -0
  110. nabu/processing/kernel_base.py +126 -0
  111. nabu/processing/medfilt_cuda.py +159 -0
  112. nabu/processing/muladd.py +29 -0
  113. nabu/processing/muladd_cuda.py +68 -0
  114. nabu/processing/padding_base.py +71 -0
  115. nabu/processing/padding_cuda.py +75 -0
  116. nabu/processing/padding_opencl.py +77 -0
  117. nabu/processing/processing_base.py +123 -0
  118. nabu/processing/roll_opencl.py +64 -0
  119. nabu/processing/rotation.py +63 -0
  120. nabu/processing/rotation_cuda.py +66 -0
  121. nabu/processing/tests/__init__.py +0 -0
  122. nabu/processing/tests/test_fft.py +268 -0
  123. nabu/processing/tests/test_fftshift.py +71 -0
  124. nabu/{misc → processing}/tests/test_histogram.py +2 -4
  125. nabu/{cuda → processing}/tests/test_medfilt.py +1 -1
  126. nabu/processing/tests/test_muladd.py +54 -0
  127. nabu/{cuda → processing}/tests/test_padding.py +119 -75
  128. nabu/processing/tests/test_roll.py +63 -0
  129. nabu/{misc → processing}/tests/test_rotation.py +3 -2
  130. nabu/processing/tests/test_transpose.py +72 -0
  131. nabu/{misc → processing}/tests/test_unsharp.py +41 -8
  132. nabu/processing/transpose.py +126 -0
  133. nabu/processing/unsharp.py +79 -0
  134. nabu/processing/unsharp_cuda.py +53 -0
  135. nabu/processing/unsharp_opencl.py +75 -0
  136. nabu/reconstruction/fbp.py +34 -10
  137. nabu/reconstruction/fbp_base.py +35 -16
  138. nabu/reconstruction/fbp_opencl.py +7 -12
  139. nabu/reconstruction/filtering.py +2 -2
  140. nabu/reconstruction/filtering_cuda.py +13 -14
  141. nabu/reconstruction/filtering_opencl.py +3 -4
  142. nabu/reconstruction/projection.py +2 -0
  143. nabu/reconstruction/rings.py +158 -1
  144. nabu/reconstruction/rings_cuda.py +218 -58
  145. nabu/reconstruction/sinogram_cuda.py +16 -12
  146. nabu/reconstruction/tests/test_deringer.py +116 -14
  147. nabu/reconstruction/tests/test_fbp.py +22 -31
  148. nabu/reconstruction/tests/test_filtering.py +11 -2
  149. nabu/resources/dataset_analyzer.py +89 -26
  150. nabu/resources/nxflatfield.py +2 -2
  151. nabu/resources/tests/test_nxflatfield.py +1 -1
  152. nabu/resources/utils.py +9 -2
  153. nabu/stitching/alignment.py +184 -0
  154. nabu/stitching/config.py +241 -39
  155. nabu/stitching/definitions.py +6 -0
  156. nabu/stitching/frame_composition.py +4 -2
  157. nabu/stitching/overlap.py +99 -3
  158. nabu/stitching/sample_normalization.py +60 -0
  159. nabu/stitching/slurm_utils.py +10 -10
  160. nabu/stitching/tests/test_alignment.py +99 -0
  161. nabu/stitching/tests/test_config.py +16 -1
  162. nabu/stitching/tests/test_overlap.py +68 -2
  163. nabu/stitching/tests/test_sample_normalization.py +49 -0
  164. nabu/stitching/tests/test_slurm_utils.py +5 -5
  165. nabu/stitching/tests/test_utils.py +3 -33
  166. nabu/stitching/tests/test_z_stitching.py +391 -22
  167. nabu/stitching/utils.py +144 -202
  168. nabu/stitching/z_stitching.py +309 -126
  169. nabu/testutils.py +18 -0
  170. nabu/thirdparty/tomocupy_remove_stripe.py +586 -0
  171. nabu/utils.py +32 -6
  172. {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/LICENSE +1 -1
  173. {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/METADATA +5 -5
  174. nabu-2024.1.0rc3.dist-info/RECORD +296 -0
  175. {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/WHEEL +1 -1
  176. {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/entry_points.txt +5 -1
  177. nabu/conftest.py +0 -14
  178. nabu/opencl/fftshift.py +0 -92
  179. nabu/opencl/tests/test_fftshift.py +0 -55
  180. nabu/opencl/tests/test_padding.py +0 -84
  181. nabu-2023.2.1.dist-info/RECORD +0 -252
  182. /nabu/cuda/src/{fftshift.cu → dfi_fftshift.cu} +0 -0
  183. {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/top_level.txt +0 -0
doc/conf.py CHANGED
@@ -19,7 +19,7 @@ sys.path.insert(0, os.path.abspath("../"))
19
19
  # -- Project information -----------------------------------------------------
20
20
 
21
21
  project = "Nabu"
22
- copyright = "2022, ESRF"
22
+ copyright = "2019-2024, ESRF"
23
23
  author = "Pierre Paleo"
24
24
 
25
25
  # -- General configuration ---------------------------------------------------
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__ = "2023.2.1"
1
+ __version__ = "2024.1.0-rc3"
2
2
  __nabu_modules__ = [
3
3
  "app",
4
4
  "cuda",
@@ -7,6 +7,7 @@ __nabu_modules__ = [
7
7
  "misc",
8
8
  "opencl",
9
9
  "pipeline",
10
+ "processing",
10
11
  "preproc",
11
12
  "reconstruction",
12
13
  "resources",
@@ -43,7 +43,7 @@ def guess_tomo_objects(my_str: str) -> tuple:
43
43
  def bootstrap_stitching():
44
44
  args = parse_params_values(
45
45
  BootstrapStitchingConfig,
46
- parser_description="Initialize a nabu configuration file",
46
+ parser_description="Initialize a 'nabu-stitching' configuration file",
47
47
  )
48
48
 
49
49
  prefilled_values = {}
nabu/app/cli_configs.py CHANGED
@@ -3,8 +3,10 @@
3
3
  #
4
4
 
5
5
  # Default configuration for "bootstrap" command
6
- from nabu.stitching.config import StitchingType
7
- from tomoscan.framereducerbase import ReduceMethod
6
+ from nabu.stitching.definitions import StitchingType
7
+ from nabu.pipeline.config_validators import str2bool
8
+
9
+ from tomoscan.framereducer.method import ReduceMethod
8
10
 
9
11
 
10
12
  BootstrapConfig = {
@@ -327,6 +329,11 @@ StitchingConfig = {
327
329
  "help": "Logging level. Can be 'debug', 'info', 'warning', 'error'. Default is 'info'.",
328
330
  "default": "info",
329
331
  },
332
+ "--only-create-master-file": {
333
+ "help": "Will create the master file with all sub files (volumes or scans). It expects the processing to be finished. It can happen if all slurm job have been submitted but you've been kicked out of the cluster of if you need to relaunch manually some failling job slurm for any reason",
334
+ "default": False,
335
+ "action": "store_true",
336
+ },
330
337
  }
331
338
 
332
339
  # Default configuration for "stitching-bootstrap" command
@@ -446,6 +453,102 @@ CreateDistortionMapHorizontallyMatchedFromPolyConfig = {
446
453
  },
447
454
  }
448
455
 
456
+ DiagToRotConfig = {
457
+ "--diag_file": dict(
458
+ required=True, help="The reconstruction file obtained by nabu-helical using the diag_zpro_run option", type=str
459
+ ),
460
+ "--entry_name": dict(
461
+ required=False,
462
+ help="entry_name. Defauls is entry0000",
463
+ default="entry0000",
464
+ ),
465
+ "--near": dict(
466
+ required=False,
467
+ help="This is a relative offset respect to the center of the radios. The cor will be searched around the provided value. If not given the optinal parameter original_scan must be the original nexus file; and the estimated core will be taken there. The netry_name parameter also must be provided in this case",
468
+ default=None,
469
+ type=float,
470
+ ),
471
+ "--original_scan": dict(
472
+ required=False,
473
+ help="The original nexus file. Required only if near parameter is not given",
474
+ default=None,
475
+ type=str,
476
+ ),
477
+ "--entry_name": dict(
478
+ required=False,
479
+ help="The original nexus file entry name. Required only if near parameter is not given",
480
+ default=None,
481
+ type=str,
482
+ ),
483
+ "--near_width": dict(
484
+ required=False,
485
+ help="For the horizontal correlation, searching the cor. The radius around the near value",
486
+ default=20,
487
+ type=int,
488
+ ),
489
+ "--low_pass": dict(
490
+ required=False,
491
+ help="Data are filtered horizontally. details smaller than the provided value are filtered out. Default is 1( gaussian sigma)",
492
+ default=1.0,
493
+ type=float,
494
+ ),
495
+ "--high_pass": dict(
496
+ required=False,
497
+ help="Data are filtered horizontally. Bumps larger than the provided value are filtered out. Default is 10( gaussian sigma)",
498
+ default=10,
499
+ type=int,
500
+ ),
501
+ "--linear_interpolation": dict(
502
+ required=False, help="If True(default) the cor will vary linearly with z_transl", default=True, type=str2bool
503
+ ),
504
+ "--use_l1_norm": dict(
505
+ required=False,
506
+ default=True,
507
+ help="If false then a L2 norm will be used for the error metric, considering the overlaps, if true L1 norm will be considered",
508
+ type=str2bool,
509
+ ),
510
+ "--cor_file": dict(required=True, help="The file where the information to correct the cor are written", type=str),
511
+ }
512
+
513
+ DiagToPixConfig = {
514
+ "--diag_file": dict(
515
+ required=True, help="The reconstruction file obtained by nabu-helical using the diag_zpro_run option", type=str
516
+ ),
517
+ "--entry_name": dict(required=False, help="entry_name. Defauls is entry0000", default="entry0000", type=str),
518
+ "--search_radius_v": dict(
519
+ required=False,
520
+ help="For the vertical correlation, The maximal error in pixels of one turn respect to a contiguous one. Default is 20 ",
521
+ default=20,
522
+ type=int,
523
+ ),
524
+ "--nexus_target": dict(
525
+ required=False,
526
+ help="If given, the mentioned file will be edited with the proper pixel size, the proper COR, and corrected x_translations",
527
+ default=None,
528
+ type=str,
529
+ ),
530
+ "--nexus_source": dict(
531
+ required=False,
532
+ help="Optionaly given, used only if nexus_target has been give. The nexus file will be edited and written on nexus_target. Otherwise nexus_target is considered to be the source",
533
+ default=None,
534
+ type=str,
535
+ ),
536
+ }
537
+
538
+ CorrectRotConfig = {
539
+ "--cor_file": dict(required=True, help="The file produce by diag_to_rot", type=str),
540
+ "--entry_name": dict(required=False, help="entry_name. Defauls is entry0000", default="entry0000", type=str),
541
+ "--nexus_target": dict(
542
+ required=True,
543
+ help="The given file will be edited with the proper pixel size, the proper COR, and corrected x_translations",
544
+ default=None,
545
+ type=str,
546
+ ),
547
+ "--nexus_source": dict(
548
+ required=True, help="The nexus file will be edited and written on nexus_target", default=None, type=str
549
+ ),
550
+ }
551
+
449
552
 
450
553
  ReduceDarkFlatConfig = {
451
554
  "dataset": {"help": "Dataset (NXtomo or EDF folder) to be treated", "mandatory": True},
@@ -504,3 +607,20 @@ ReduceDarkFlatConfig = {
504
607
  "required": False,
505
608
  },
506
609
  }
610
+
611
+ ShowReconstructionTimingsConfig = {
612
+ "logfile": {
613
+ "help": "Path to the log file.",
614
+ "default": "",
615
+ "mandatory": True,
616
+ },
617
+ "cutoff": {
618
+ "help": "Cut-off parameter. Timings below this value will be discarded. For a upper-bound cutoff, provide a value in the form 'low, high'",
619
+ "default": None,
620
+ },
621
+ "type": {
622
+ "help": "How to display the result. Default is a pie chart. Possible values are: pie, bars, violin",
623
+ "default": "pie",
624
+ "type": str,
625
+ },
626
+ }
nabu/app/composite_cor.py CHANGED
@@ -5,8 +5,10 @@ import numpy as np
5
5
  import re
6
6
 
7
7
  from nabu.resources.dataset_analyzer import HDF5DatasetAnalyzer
8
- from nabu.pipeline.estimators import CompositeCOREstimator
8
+ from nabu.pipeline.estimators import CompositeCOREstimator, estimate_cor
9
9
  from nabu.resources.nxflatfield import update_dataset_info_flats_darks
10
+ from nabu.resources.utils import extract_parameters
11
+ from nxtomo.application.nxtomo import NXtomo
10
12
  from .. import version
11
13
  from .cli_configs import CompositeCorConfig
12
14
  from .utils import parse_params_values
@@ -82,6 +84,29 @@ def composite_cor_entry_point(args_dict):
82
84
 
83
85
  dataset_info = HDF5DatasetAnalyzer(nexus_name, extra_options={"h5_entry": args.entry_name})
84
86
  update_dataset_info_flats_darks(dataset_info, flatfield_mode=1)
87
+
88
+ ### JL start ###
89
+ # Extract CoR parameters from configuration file
90
+ try:
91
+ cor_options = extract_parameters(args.cor_options, sep=";")
92
+ except Exception as exc:
93
+ msg = "Could not extract parameters from cor_options: %s" % (str(exc))
94
+ raise ValueError(msg)
95
+ ### JL end ###
96
+
97
+ # JL start ###
98
+ #: next bit will be done in estimate
99
+ # if "near_pos" not in args.cor_options:
100
+ # scan = NXtomo()
101
+ # scan.load(file_path=nexus_name, data_path=args.entry_name)
102
+ # estimated_near = scan.instrument.detector.estimated_cor_from_motor
103
+ #
104
+ # cor_options = args.cor_options + f" ; near_pos = {estimated_near} "
105
+ #
106
+ # else:
107
+ # cor_options = args.cor_options
108
+ ### JL end ###
109
+
85
110
  cor_finder = CompositeCOREstimator(
86
111
  dataset_info,
87
112
  oversampling=args.oversampling,
@@ -89,7 +114,7 @@ def composite_cor_entry_point(args_dict):
89
114
  n_subsampling_y=args.n_subsampling_y,
90
115
  take_log=True,
91
116
  spike_threshold=0.04,
92
- cor_options=args.cor_options,
117
+ cor_options=cor_options,
93
118
  norm_order=1,
94
119
  )
95
120
 
@@ -0,0 +1,70 @@
1
+ from .. import version
2
+ from os import environ
3
+
4
+ import argparse
5
+ import shutil
6
+ import os
7
+ import sys
8
+ import re
9
+ import h5py
10
+ import numpy as np
11
+
12
+
13
+ from ..resources.logger import LoggerOrPrint
14
+ from .utils import parse_params_values
15
+ from .cli_configs import CorrectRotConfig
16
+ from silx.io.dictdump import h5todict
17
+
18
+ from nxtomo.application.nxtomo import NXtomo
19
+
20
+ import h5py
21
+ from nabu.utils import DictToObj
22
+
23
+
24
+ def main(user_args=None):
25
+ """Applies the correction found by diag_to_rot to a nexus file"""
26
+
27
+ if user_args is None:
28
+ user_args = sys.argv[1:]
29
+
30
+ args = DictToObj(
31
+ parse_params_values(
32
+ CorrectRotConfig,
33
+ parser_description=main.__doc__,
34
+ program_version="nabu " + version,
35
+ user_args=user_args,
36
+ )
37
+ )
38
+
39
+ # now we read the results of the diag_to_rot utility, they are in the cor_file parameter
40
+ # of the cli
41
+ cor_data = DictToObj(h5todict(args.cor_file, "/"))
42
+
43
+ my_cor = cor_data.cor[0]
44
+ # we will take my_cor as cor at the first angular position
45
+ # and then we correct the x_translation at the other angles
46
+
47
+ # We now load the nexus that we wish to correct
48
+ nx_tomo = NXtomo().load(args.nexus_source, args.entry_name)
49
+
50
+ # The cor_file that we use for correction
51
+ # is providing us with the z_m that gives for each
52
+ # cor position found in the cor array the corresponding value of
53
+ # the translation along z (in meters)
54
+ z_translation = nx_tomo.sample.z_translation.value
55
+ z_translation = z_translation - z_translation[0]
56
+
57
+ # now we interpolate to find the correction
58
+ # for each position of the encoders
59
+ cors = np.interp(z_translation, cor_data.z_m, cor_data.cor)
60
+
61
+ # this is the correction
62
+ x_correction = nx_tomo.instrument.detector.x_pixel_size.value * (cors - my_cor) # we are in meters here
63
+
64
+ # and we apply it to the nexus that we have loaded
65
+ nx_tomo.sample.x_translation = nx_tomo.sample.x_translation.value + x_correction
66
+
67
+ # finally we write it to the corrected nexus file
68
+ nx_tomo.save(file_path=args.nexus_target, data_path=args.entry_name, overwrite=True)
69
+
70
+ return 0
@@ -9,7 +9,7 @@ from ..utils import DictToObj
9
9
  from ..resources.logger import Logger, LoggerOrPrint
10
10
 
11
11
 
12
- def horizontal_match_entry_point(user_args=None):
12
+ def create_distortion_maps_entry_point(user_args=None):
13
13
  """This application builds two arrays. Let us call them map_x and map_z. Both are 2D arrays with shape given by (nz, nx).
14
14
  These maps are meant to be used to generate a corrected detector image, using them to obtain the pixel (i,j) of the corrected
15
15
  image by interpolating the raw data at position ( map_z(i,j), map_x(i,j) ).
@@ -45,26 +45,40 @@ def horizontal_match_entry_point(user_args=None):
45
45
  user_args = sys.argv[1:]
46
46
  args_dict = parse_params_values(
47
47
  CreateDistortionMapHorizontallyMatchedFromPolyConfig,
48
- parser_description=horizontal_match.__doc__,
48
+ parser_description=create_maps_x_and_z.__doc__,
49
49
  program_version="nabu " + version,
50
50
  user_args=user_args,
51
51
  )
52
- horizontal_match(args_dict)
53
- # here we have been called by the cli. The return value 0 means OK
52
+
53
+ logger = Logger("create_distortion_maps", level=user_args["loglevel"], logfile="create_distortion_maps.log")
54
+
55
+ coords_source_x, coords_source_z, new_axis_pos = create_maps_x_and_z(args_dict)
56
+
57
+ with h5py.File(args_dict["target_file"], "w") as f:
58
+ f["coords_source_x"] = coords_source_x
59
+ f["coords_source_z"] = coords_source_z
60
+
61
+ if new_axis_pos is not None:
62
+ logger.info("New axis position at %e it was previously %e " % (new_axis_pos, args_dict["axis_pos"]))
63
+
54
64
  return 0
55
65
 
56
66
 
57
- def horizontal_match(args_dict):
67
+ def create_maps_x_and_z(args_dict):
58
68
  """This method is meant for those applications which wants to use the functionalities of the poly2map
59
69
  entry point through a standar python API.
60
70
  The argument arg_dict must contain the keys that you can find in cli_configs.py:
61
- CreateDistortionMapHorizontallyMatchedFromPolyConfig
71
+ CreateDistortionMapHorizontallyMatchedFromPolyConfig
62
72
  Look at this files for variables and their meaning and defaults
73
+ Parameters::
74
+ args_dict : dict
75
+ a dictionary containing keys : center_x, center_z, nz, nx, c2, c4, axis_pos
76
+ return:
77
+ max_x, map_z, new_rot_pos
78
+
63
79
  """
64
80
  args = DictToObj(args_dict)
65
81
 
66
- logger = Logger("horizontal_match", level=args.loglevel, logfile="horizontal_match.log")
67
-
68
82
  nz, nx = args.nz, args.nx
69
83
  center_x, center_z = (args.center_x, args.center_z)
70
84
 
@@ -115,15 +129,25 @@ def horizontal_match(args_dict):
115
129
  coords_source_z = coords_z * distances_data_sources / distances_goal + center_z
116
130
  coords_source_x = coords_x * distances_data_sources / distances_goal + center_x
117
131
 
118
- with h5py.File(args.target_file, "w") as f:
119
- f["coords_source_x"] = coords_source_x
120
- f["coords_source_z"] = coords_source_z
132
+ new_axis_pos = None
121
133
 
122
134
  if args.axis_pos is not None:
123
- coord_axis = args.axis_pos - center_x
124
- new_pos = (polynomial(coord_axis) - final_grid_shift) / final_grid_rescaling + center_x
125
- logger.info("New axis position at %e it was previously %e " % (new_pos, args.axis_pos))
126
-
127
- return new_pos
128
- else:
129
- return None
135
+ # here we search on the central line a point new_axis_pos
136
+ # such that
137
+ # coords_source_x[ i_central_y, nuova_axis_pos ] == axis_pos
138
+ #
139
+ n_y, n_x = coords_source_x.shape
140
+ x_coordinates_central_line = coords_source_x[n_y // 2]
141
+
142
+ if np.any(np.less_equal(np.diff(x_coordinates_central_line), 0)):
143
+ message = """ Error in the coordinates map, the X coordinates are not monotonous on the central line """
144
+ raise ValueError(message)
145
+ i1 = np.searchsorted(x_coordinates_central_line, args.axis_pos)
146
+ i1 = np.clip(i1, 1, n_x - 1)
147
+ i0 = i1 - 1
148
+ val0 = x_coordinates_central_line[i0]
149
+ val1 = x_coordinates_central_line[i1]
150
+ fract = (args.axis_pos - val0) / (val1 - val0)
151
+ new_axis_pos = i0 * (1 - fract) + i1 * fract
152
+
153
+ return coords_source_x, coords_source_z, new_axis_pos