tomwer 1.3.5__py3-none-any.whl → 1.3.7__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 (124) hide show
  1. orangecontrib/tomwer/test/TestAcquisition.py +246 -0
  2. orangecontrib/tomwer/widgets/cluster/test/test_future_supervisorow.py +87 -0
  3. orangecontrib/tomwer/widgets/cluster/test/test_slurm_clusterow.py +67 -0
  4. orangecontrib/tomwer/widgets/control/test/test_advancement.py +51 -0
  5. orangecontrib/tomwer/widgets/control/test/test_data_validator.py +55 -0
  6. orangecontrib/tomwer/widgets/control/test/test_datadiscovery.py +131 -0
  7. orangecontrib/tomwer/widgets/control/test/test_datalist.py +70 -0
  8. orangecontrib/tomwer/widgets/control/test/test_datalistener.py +137 -0
  9. orangecontrib/tomwer/widgets/control/test/test_dataselector.py +95 -0
  10. orangecontrib/tomwer/widgets/control/test/test_datawatcher.py +436 -0
  11. orangecontrib/tomwer/widgets/control/test/test_emailow.py +29 -0
  12. orangecontrib/tomwer/widgets/control/test/test_notifier.py +51 -0
  13. orangecontrib/tomwer/widgets/control/test/test_nxtomo_concatenate_ow.py +64 -0
  14. orangecontrib/tomwer/widgets/control/test/test_nxtomomill.py +160 -0
  15. orangecontrib/tomwer/widgets/control/test/test_reduce_dark_flat_selector.py +40 -0
  16. orangecontrib/tomwer/widgets/control/test/test_singletomoobj.py +40 -0
  17. orangecontrib/tomwer/widgets/control/test/test_timerow.py +51 -0
  18. orangecontrib/tomwer/widgets/control/test/test_tomoobj_serie.py +96 -0
  19. orangecontrib/tomwer/widgets/control/test/test_volume_selector.py +69 -0
  20. orangecontrib/tomwer/widgets/control/test/test_volumesymlink.py +51 -0
  21. orangecontrib/tomwer/widgets/debugtools/test/test_dataset_generator.py +57 -0
  22. orangecontrib/tomwer/widgets/debugtools/test/test_object_inspector.py +62 -0
  23. orangecontrib/tomwer/widgets/other/test/test_pythonscript.py +31 -0
  24. orangecontrib/tomwer/widgets/reconstruction/test/test_axis.py +224 -0
  25. orangecontrib/tomwer/widgets/reconstruction/test/test_cast_volumeow.py +85 -0
  26. orangecontrib/tomwer/widgets/reconstruction/test/test_dark_refs_widget.py +136 -0
  27. orangecontrib/tomwer/widgets/reconstruction/test/test_delta_beta_selector.py +15 -0
  28. orangecontrib/tomwer/widgets/reconstruction/test/test_i_norm.py +226 -0
  29. orangecontrib/tomwer/widgets/reconstruction/test/test_nabu_helical_prepare_weights_double.py +20 -0
  30. orangecontrib/tomwer/widgets/reconstruction/test/test_nabu_volume.py +100 -0
  31. orangecontrib/tomwer/widgets/reconstruction/test/test_nabu_widget.py +107 -0
  32. orangecontrib/tomwer/widgets/reconstruction/test/test_sa_delta_beta.py +194 -0
  33. orangecontrib/tomwer/widgets/reconstruction/test/test_saaxis.py +220 -0
  34. orangecontrib/tomwer/widgets/stitching/test/test_zstitching.py +308 -0
  35. orangecontrib/tomwer/widgets/test/test_conditions.py +111 -0
  36. orangecontrib/tomwer/widgets/test/test_darkref.py +251 -0
  37. orangecontrib/tomwer/widgets/test/test_foldertransfert.py +131 -0
  38. orangecontrib/tomwer/widgets/visualization/test/test_dataviewerow.py +83 -0
  39. orangecontrib/tomwer/widgets/visualization/test/test_diffviewerow.py +65 -0
  40. orangecontrib/tomwer/widgets/visualization/test/test_live_sliceow.py +63 -0
  41. orangecontrib/tomwer/widgets/visualization/test/test_nxtomo_metadata_viewer.py +29 -0
  42. orangecontrib/tomwer/widgets/visualization/test/test_radio_stackow.py +56 -0
  43. orangecontrib/tomwer/widgets/visualization/test/test_sample_movedow.py +72 -0
  44. orangecontrib/tomwer/widgets/visualization/test/test_sinogram_viewerow.py +56 -0
  45. orangecontrib/tomwer/widgets/visualization/test/test_slice_stackow.py +57 -0
  46. orangecontrib/tomwer/widgets/visualization/test/test_volume_viewerow.py +57 -0
  47. tomwer/core/log/test/test_processlog.py +41 -0
  48. tomwer/core/process/control/datalistener/datalistener.py +11 -11
  49. tomwer/core/process/edit/test/test_darkflatpatch.py +269 -0
  50. tomwer/core/process/edit/test/test_imagekey_editor.py +125 -0
  51. tomwer/core/process/icat/test/test_create_screenshots.py +98 -0
  52. tomwer/core/process/icat/test/test_gallery.py +170 -0
  53. tomwer/core/process/reconstruction/axis/axis.py +3 -3
  54. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +3 -2
  55. tomwer/core/process/reconstruction/nabu/nabucommon.py +3 -4
  56. tomwer/core/process/reconstruction/nabu/nabuslices.py +4 -4
  57. tomwer/core/process/reconstruction/nabu/nabuvolume.py +2 -5
  58. tomwer/core/process/reconstruction/nabu/test/test_castvolume.py +143 -0
  59. tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +203 -0
  60. tomwer/core/process/reconstruction/nabu/test/test_nabunormalization.py +222 -0
  61. tomwer/core/process/script/test/test_script.py +68 -0
  62. tomwer/core/process/stitching/test/test_metadataholder.py +17 -0
  63. tomwer/core/process/task.py +3 -2
  64. tomwer/core/process/test/test_data_transfer.py +4 -3
  65. tomwer/core/process/visualization/test/test_data_viewer.py +39 -0
  66. tomwer/core/process/visualization/test/test_diff_viewer.py +39 -0
  67. tomwer/core/process/visualization/test/test_image_stack_viewer.py +41 -0
  68. tomwer/core/process/visualization/test/test_radio_stack.py +39 -0
  69. tomwer/core/process/visualization/test/test_sample_moved.py +41 -0
  70. tomwer/core/process/visualization/test/test_sinogram_viewer.py +39 -0
  71. tomwer/core/process/visualization/test/test_slice_stack.py +39 -0
  72. tomwer/core/process/visualization/test/test_volume_viewer.py +39 -0
  73. tomwer/core/scan/blissscan.py +3 -3
  74. tomwer/core/scan/nxtomoscan.py +2 -2
  75. tomwer/core/scan/scanbase.py +5 -6
  76. tomwer/core/utils/test/test_image.py +30 -0
  77. tomwer/core/utils/test/test_nxtomo.py +66 -0
  78. tomwer/core/utils/test/test_scan_utils.py +46 -0
  79. tomwer/core/utils/test/test_time.py +6 -0
  80. tomwer/core/volume/test/test_volumes.py +21 -0
  81. tomwer/gui/control/reducedarkflatselector.py +2 -2
  82. tomwer/gui/control/serie/test/test_creator.py +451 -0
  83. tomwer/gui/control/serie/test/test_nxtomo_concatenate.py +21 -0
  84. tomwer/gui/edit/dkrfpatch.py +4 -4
  85. tomwer/gui/edit/nxtomowarmer.py +3 -2
  86. tomwer/gui/icat/test/test_create_screenshots_gui.py +23 -0
  87. tomwer/gui/icat/test/test_gallery_gui.py +37 -0
  88. tomwer/gui/imagefromfile.py +2 -2
  89. tomwer/gui/reconstruction/nabu/test/test_check.py +92 -0
  90. tomwer/gui/reconstruction/nabu/test/test_ctf.py +46 -0
  91. tomwer/gui/reconstruction/nabu/test/test_helical.py +21 -0
  92. tomwer/gui/reconstruction/nabu/test/test_nabu_preprocessing.py +81 -0
  93. tomwer/gui/reconstruction/normalization/test/test_intensity.py +119 -0
  94. tomwer/gui/stitching/config/tests/test_axisparams.py +25 -0
  95. tomwer/gui/stitching/tests/test_axis_ordered_list.py +21 -0
  96. tomwer/gui/stitching/tests/test_normalization.py +27 -0
  97. tomwer/gui/stitching/tests/test_preview.py +85 -0
  98. tomwer/gui/stitching/tests/test_stitching_raw.py +110 -0
  99. tomwer/gui/stitching/tests/test_z_stitching.py +67 -0
  100. tomwer/gui/stitching/tests/utils.py +79 -0
  101. tomwer/gui/stitching/z_stitching/tests/test_fine_estimation.py +35 -0
  102. tomwer/gui/stitching/z_stitching/tests/test_raw_estimation.py +215 -0
  103. tomwer/gui/stitching/z_stitching/tests/test_stitching_window.py +51 -0
  104. tomwer/gui/utils/test/test_completer.py +67 -0
  105. tomwer/gui/utils/test/test_line_selector.py +21 -0
  106. tomwer/gui/utils/test/test_splashscreen.py +8 -0
  107. tomwer/gui/utils/test/test_vignettes.py +68 -0
  108. tomwer/io/utils/h5pyutils.py +3 -7
  109. tomwer/io/utils/test/test_raw_and_processed_data.py +10 -0
  110. tomwer/io/utils/test/test_utils.py +92 -0
  111. tomwer/io/utils/utils.py +3 -3
  112. tomwer/synctools/stacks/reconstruction/castvolume.py +20 -5
  113. tomwer/tests/test_ewoks/test_conversion.py +104 -0
  114. tomwer/tests/test_ewoks/test_single_node_execution.py +112 -0
  115. tomwer/tests/test_ewoks/test_workflows.py +160 -0
  116. tomwer/version.py +1 -1
  117. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/METADATA +1 -1
  118. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/RECORD +124 -27
  119. /tomwer-1.3.5-py3.11-nspkg.pth → /tomwer-1.3.7-py3.11-nspkg.pth +0 -0
  120. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/LICENSE +0 -0
  121. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/WHEEL +0 -0
  122. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/entry_points.txt +0 -0
  123. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/namespace_packages.txt +0 -0
  124. {tomwer-1.3.5.dist-info → tomwer-1.3.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016-2017 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["H. Payno"]
27
+ __license__ = "MIT"
28
+ __date__ = "18/03/2022"
29
+
30
+
31
+ from tomwer.core.log.logger import TomwerLogger
32
+
33
+
34
+ def test_process_log():
35
+ logger = TomwerLogger("tomtom")
36
+ logger.processStarted("process started")
37
+ logger.processEnded("process ended")
38
+ logger.processSkipped("process skipped")
39
+ logger.inform("information")
40
+ logger.processSucceed("process succeed")
41
+ logger.processFailed("process failed")
@@ -37,7 +37,7 @@ import typing
37
37
  from ewokscore.task import Task as EwoksTask
38
38
  from nxtomomill import converter as nxtomomill_converter
39
39
  from silx.io.utils import h5py_read_dataset
40
- from tomoscan.io import HDF5File
40
+ from silx.io.utils import open as open_hdf5
41
41
 
42
42
  import tomwer.version
43
43
  from tomwer.core import settings
@@ -229,7 +229,7 @@ class DataListener(BaseProcessInfo):
229
229
  """Return the list of scans dir for this bliss_file / entry"""
230
230
 
231
231
  def get_scan_indexes():
232
- with HDF5File(bliss_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
232
+ with open_hdf5(bliss_file) as h5f:
233
233
  entry_node = h5f[entry]
234
234
  if _SCAN_NUMBER_PATH in entry_node:
235
235
  return h5py_read_dataset(entry_node[_SCAN_NUMBER_PATH])
@@ -254,7 +254,7 @@ class DataListener(BaseProcessInfo):
254
254
  """Return the proposal file of the experimentation if registred by the
255
255
  data listener"""
256
256
  if entry is None:
257
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
257
+ with open_hdf5(process_file) as h5f:
258
258
  entries = BaseProcessInfo._get_process_nodes(
259
259
  root_node=h5f, process=DataListener
260
260
  )
@@ -269,7 +269,7 @@ class DataListener(BaseProcessInfo):
269
269
  entry = list(entries.keys())[0]
270
270
  _logger.info("take %s as default entry" % entry)
271
271
 
272
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
272
+ with open_hdf5(process_file) as h5f:
273
273
  dl_nodes = BaseProcessInfo._get_process_nodes(
274
274
  root_node=h5f[entry], process=DataListener
275
275
  )
@@ -311,7 +311,7 @@ class DataListener(BaseProcessInfo):
311
311
  """Return the proposal file of the experimentation if registred by the
312
312
  data listener"""
313
313
  if entry is None:
314
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
314
+ with open_hdf5(process_file) as h5f:
315
315
  entries = BaseProcessInfo._get_process_nodes(
316
316
  root_node=h5f, process=DataListener
317
317
  )
@@ -326,7 +326,7 @@ class DataListener(BaseProcessInfo):
326
326
  entry = list(entries.keys())[0]
327
327
  _logger.info("take %s as default entry" % entry)
328
328
 
329
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
329
+ with open_hdf5(process_file) as h5f:
330
330
  dl_nodes = BaseProcessInfo._get_process_nodes(
331
331
  root_node=h5f[entry], process=DataListener
332
332
  )
@@ -360,7 +360,7 @@ class DataListener(BaseProcessInfo):
360
360
  """Return the proposal file of the experimentation if registred by the
361
361
  data listener"""
362
362
  if entry is None:
363
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
363
+ with open_hdf5(process_file) as h5f:
364
364
  entries = BaseProcessInfo._get_process_nodes(
365
365
  root_node=h5f, process=DataListener
366
366
  )
@@ -375,7 +375,7 @@ class DataListener(BaseProcessInfo):
375
375
  entry = list(entries.keys())[0]
376
376
  _logger.info("take %s as default entry" % entry)
377
377
 
378
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
378
+ with open_hdf5(process_file) as h5f:
379
379
  dl_nodes = BaseProcessInfo._get_process_nodes(
380
380
  root_node=h5f[entry], process=DataListener
381
381
  )
@@ -410,7 +410,7 @@ class DataListener(BaseProcessInfo):
410
410
  specific sequence data
411
411
  """
412
412
  if entry is None:
413
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
413
+ with open_hdf5(process_file) as h5f:
414
414
  entries = BaseProcessInfo._get_process_nodes(
415
415
  root_node=h5f, process=DataListener
416
416
  )
@@ -425,7 +425,7 @@ class DataListener(BaseProcessInfo):
425
425
  entry = list(entries.keys())[0]
426
426
  _logger.info("take %s as default entry" % entry)
427
427
 
428
- with HDF5File(process_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
428
+ with open_hdf5(process_file) as h5f:
429
429
  dl_nodes = BaseProcessInfo._get_process_nodes(
430
430
  root_node=h5f[entry], process=DataListener
431
431
  )
@@ -503,7 +503,7 @@ class DataListener(BaseProcessInfo):
503
503
  # write
504
504
  def sequence_is_finished():
505
505
  try:
506
- with HDF5File(bliss_file, "r", swmr=DataListener.SWMR_MODE) as h5f:
506
+ with open_hdf5(bliss_file) as h5f:
507
507
  end_scan_path = "/".join((entry, "end_time"))
508
508
  return end_scan_path in h5f
509
509
  except Exception:
@@ -0,0 +1,269 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2017-2021 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["H. Payno"]
27
+ __license__ = "MIT"
28
+ __date__ = "18/06/2021"
29
+
30
+
31
+ import os
32
+ import shutil
33
+ import tempfile
34
+ import unittest
35
+
36
+ import h5py
37
+ import numpy
38
+ from silx.io.url import DataUrl
39
+ from silx.io.utils import h5py_read_dataset
40
+ from tomoscan.esrf.scan.mock import MockNXtomo
41
+
42
+ from tomwer.core.process.edit.darkflatpatch import DarkFlatPatchTask
43
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
44
+
45
+
46
+ class BaseTestAddDarkAndFlats(unittest.TestCase):
47
+ """
48
+ Unit test on nxtomomill.utils.add_dark_flat_nx_file function
49
+ """
50
+
51
+ def setUp(self) -> None:
52
+ self.tmpdir = tempfile.mkdtemp()
53
+ simple_nx_path = os.path.join(self.tmpdir, "simple_case")
54
+ self.dim = 55
55
+ self.nproj = 20
56
+ self._simple_nx = MockNXtomo(
57
+ scan_path=simple_nx_path,
58
+ n_proj=self.nproj,
59
+ n_ini_proj=self.nproj,
60
+ create_ini_dark=False,
61
+ create_ini_flat=False,
62
+ create_final_flat=False,
63
+ dim=self.dim,
64
+ ).scan
65
+ with h5py.File(self._simple_nx.master_file, mode="r") as h5s:
66
+ data_path = "/".join(
67
+ (self._simple_nx.entry, "instrument", "detector", "data")
68
+ )
69
+ self._raw_data = h5py_read_dataset(h5s[data_path])
70
+ nx_with_vds_path = os.path.join(self.tmpdir, "case_with_vds")
71
+ self._nx_with_virtual_dataset = MockNXtomo(
72
+ scan_path=nx_with_vds_path,
73
+ n_proj=0,
74
+ n_ini_proj=0,
75
+ create_ini_dark=False,
76
+ create_ini_flat=False,
77
+ create_final_flat=False,
78
+ dim=self.dim,
79
+ ).scan
80
+ self._create_vds(
81
+ source_file=self._simple_nx.master_file,
82
+ source_data_path=self._simple_nx.entry,
83
+ target_file=self._nx_with_virtual_dataset.master_file,
84
+ target_data_path=self._nx_with_virtual_dataset.entry,
85
+ copy_other_data=True,
86
+ )
87
+ self._patch_nxtomo_flags(self._nx_with_virtual_dataset)
88
+
89
+ nx_with_vds_path_and_links = os.path.join(
90
+ self.tmpdir, "case_with_vds_and_links"
91
+ )
92
+ self._nx_with_virtual_dataset_with_link = MockNXtomo(
93
+ scan_path=nx_with_vds_path_and_links,
94
+ n_proj=0,
95
+ n_ini_proj=0,
96
+ create_ini_dark=False,
97
+ create_ini_flat=False,
98
+ create_final_flat=False,
99
+ dim=self.dim,
100
+ ).scan
101
+ self._create_vds(
102
+ source_file=self._simple_nx.master_file,
103
+ source_data_path=self._simple_nx.entry,
104
+ target_file=self._nx_with_virtual_dataset_with_link.master_file,
105
+ target_data_path=self._nx_with_virtual_dataset_with_link.entry,
106
+ copy_other_data=True,
107
+ )
108
+ self._patch_nxtomo_flags(self._nx_with_virtual_dataset_with_link)
109
+
110
+ # create dark
111
+ self.start_dark = (
112
+ numpy.random.random((self.dim * self.dim))
113
+ .reshape(1, self.dim, self.dim)
114
+ .astype("f")
115
+ )
116
+ self.start_dark_file = os.path.join(self.tmpdir, "dark.hdf5")
117
+ self.start_dark_entry = "data"
118
+ self.start_dark_url = self._save_raw(
119
+ data=self.start_dark,
120
+ entry=self.start_dark_entry,
121
+ file_path=self.start_dark_file,
122
+ )
123
+
124
+ self.end_dark = (
125
+ numpy.random.random((self.dim * self.dim * 2))
126
+ .reshape(2, self.dim, self.dim)
127
+ .astype("f")
128
+ )
129
+ self.end_dark_file = os.path.join(self.tmpdir, "dark.hdf5")
130
+ self.end_dark_entry = "data2"
131
+ self.end_dark_url = self._save_raw(
132
+ data=self.end_dark, entry=self.end_dark_entry, file_path=self.end_dark_file
133
+ )
134
+
135
+ # create flats
136
+ self.start_flat = (
137
+ numpy.random.random((self.dim * self.dim * 3))
138
+ .reshape(3, self.dim, self.dim)
139
+ .astype("f")
140
+ )
141
+ self.start_flat_file = os.path.join(self.tmpdir, "start_flat.hdf5")
142
+ self.start_flat_entry = "/root/flat"
143
+ self.start_flat_url = self._save_raw(
144
+ data=self.start_flat,
145
+ entry=self.start_flat_entry,
146
+ file_path=self.start_flat_file,
147
+ )
148
+
149
+ self.end_flat = (
150
+ numpy.random.random((self.dim * self.dim))
151
+ .reshape(1, self.dim, self.dim)
152
+ .astype("f")
153
+ )
154
+ # save the end flat in the simple case file to insure all cases are
155
+ # consider
156
+ self.end_flat_file = self._simple_nx.master_file
157
+ self.end_flat_entry = "flat"
158
+ self.end_flat_url = self._save_raw(
159
+ data=self.end_flat, entry=self.end_flat_entry, file_path=self.end_flat_file
160
+ )
161
+
162
+ def _save_raw(self, data, entry, file_path) -> DataUrl:
163
+ with h5py.File(file_path, mode="a") as h5s:
164
+ h5s[entry] = data
165
+ return DataUrl(file_path=file_path, data_path=entry, scheme="silx")
166
+
167
+ def _create_vds(
168
+ self,
169
+ source_file: str,
170
+ source_data_path: str,
171
+ target_file: str,
172
+ target_data_path: str,
173
+ copy_other_data: bool,
174
+ ):
175
+ """Create virtual dataset and links from source to target
176
+
177
+ :param str source_file:
178
+ :param str source_data_path:
179
+ :param str target_file:
180
+ :param str target_data_path:
181
+ :param bool copy_other_data: we want to create two cases: one copying
182
+ datasets 'image_key'... and the other
183
+ one linking them. Might have a difference
184
+ of behavior when overwriting for example
185
+ """
186
+ assert source_file != target_file, "file should be different"
187
+ # link data
188
+ n_frames = 0
189
+ # for now we only consider the original data
190
+ with h5py.File(source_file, mode="r") as o_h5s:
191
+ old_path = os.path.join(source_data_path, "instrument", "detector", "data")
192
+ n_frames += o_h5s[old_path].shape[0]
193
+ shape = o_h5s[old_path].shape
194
+ data_type = o_h5s[old_path].dtype
195
+
196
+ layout = h5py.VirtualLayout(shape=shape, dtype=data_type)
197
+ assert os.path.exists(source_file)
198
+ with h5py.File(source_file, mode="r") as ppp:
199
+ assert source_data_path in ppp
200
+ layout[:] = h5py.VirtualSource(path_or_dataset=o_h5s[old_path])
201
+
202
+ det_path = os.path.join(target_data_path, "instrument", "detector")
203
+ with h5py.File(target_file, mode="a") as h5s:
204
+ detector_node = h5s.require_group(det_path)
205
+ detector_node.create_virtual_dataset("data", layout, fillvalue=-5)
206
+
207
+ for path in (
208
+ os.path.join("instrument", "detector", "image_key"),
209
+ os.path.join("instrument", "detector", "image_key_control"),
210
+ os.path.join("instrument", "detector", "count_time"),
211
+ os.path.join("sample", "rotation_angle"),
212
+ ):
213
+ old_path = os.path.join(source_data_path, path)
214
+ new_path = os.path.join(target_data_path, path)
215
+ with h5py.File(target_file, mode="a") as h5s:
216
+ if copy_other_data:
217
+ with h5py.File(source_file, mode="r") as o_h5s:
218
+ if new_path in h5s:
219
+ del h5s[new_path]
220
+ h5s[new_path] = h5py_read_dataset(o_h5s[old_path])
221
+ elif source_file == target_file:
222
+ h5s[new_path] = h5py.SoftLink(old_path)
223
+ else:
224
+ relpath = os.path.relpath(source_file, os.path.dirname(target_file))
225
+ h5s[new_path] = h5py.ExternalLink(relpath, old_path)
226
+
227
+ def _patch_nxtomo_flags(self, scan):
228
+ """Insure necessary flags are here"""
229
+ with h5py.File(scan.master_file, mode="a") as h5s:
230
+ instrument_path = os.path.join(scan.entry, "instrument")
231
+ instrument_node = h5s.require_group(instrument_path)
232
+ if "NX_class" not in instrument_node.attrs:
233
+ instrument_node.attrs["NX_class"] = "NXinstrument"
234
+ detector_node = instrument_node.require_group("detector")
235
+ if "NX_class" not in detector_node.attrs:
236
+ detector_node.attrs["NX_class"] = "NXdetector"
237
+ if "data" in instrument_node:
238
+ if "interpretation" not in instrument_node.attrs:
239
+ instrument_node["data"].attrs["interpretation"] = "image"
240
+
241
+ sample_path = os.path.join(scan.entry, "sample")
242
+ sample_node = h5s.require_group(sample_path)
243
+ if "NX_class" not in sample_node:
244
+ sample_node.attrs["NX_class"] = "NXsample"
245
+
246
+ def tearDown(self) -> None:
247
+ shutil.rmtree(self.tmpdir)
248
+
249
+
250
+ class TestDaarkFlatPatch(BaseTestAddDarkAndFlats):
251
+ def test(self):
252
+ scan = NXtomoScan(
253
+ self._nx_with_virtual_dataset_with_link.master_file,
254
+ self._nx_with_virtual_dataset_with_link.entry,
255
+ )
256
+ process = DarkFlatPatchTask(
257
+ inputs={
258
+ "data": scan,
259
+ "serialize_output_data": False,
260
+ "configuration": {
261
+ "darks_start": self.start_dark_url,
262
+ },
263
+ },
264
+ )
265
+ process.definition()
266
+ process.program_version()
267
+ process.program_name()
268
+ # TODO: properties should be part of inputs
269
+ process.run()
@@ -0,0 +1,125 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2017-2021 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["H. Payno"]
27
+ __license__ = "MIT"
28
+ __date__ = "18/06/2021"
29
+
30
+
31
+ import os
32
+ import shutil
33
+ import tempfile
34
+ import unittest
35
+
36
+ import pytest
37
+ from nxtomo.nxobject.nxdetector import ImageKey
38
+
39
+ from tomwer.core.process.edit.imagekeyeditor import (
40
+ ImageKeyEditorTask,
41
+ ImageKeyUpgraderTask,
42
+ )
43
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
44
+ from tomwer.core.utils.scanutils import MockNXtomo
45
+
46
+
47
+ class TestImageKeyEditor(unittest.TestCase):
48
+ def setUp(self):
49
+ self.tempdir = tempfile.mkdtemp()
50
+ dim = 10
51
+ mock = MockNXtomo(
52
+ scan_path=os.path.join(self.tempdir, "scan1"),
53
+ n_proj=10,
54
+ n_ini_proj=10,
55
+ scan_range=180,
56
+ dim=dim,
57
+ )
58
+ self.scan = mock.scan
59
+
60
+ def tearDown(self):
61
+ shutil.rmtree(self.tempdir)
62
+
63
+ def test(self):
64
+ process = ImageKeyEditorTask(
65
+ inputs={
66
+ "data": self.scan,
67
+ "serialize_output_data": False,
68
+ "configuration": {
69
+ "modifications": {
70
+ 0: ImageKey.INVALID.value,
71
+ 3: ImageKey.ALIGNMENT.value,
72
+ },
73
+ },
74
+ }
75
+ )
76
+ process.definition()
77
+ process.program_version()
78
+ process.program_name()
79
+ process.run()
80
+
81
+
82
+ def test_ImageKeyUpgraderTask(tmp_path):
83
+ """
84
+ test ImageKeyUpgraderTask task
85
+ """
86
+ test_dir = tmp_path / "test_image_key_upgrader"
87
+ os.makedirs(test_dir)
88
+ scan = MockNXtomo(
89
+ scan_path=test_dir,
90
+ n_proj=20,
91
+ n_ini_proj=20,
92
+ create_ini_dark=False,
93
+ ).scan
94
+
95
+ operations = {
96
+ ImageKey.PROJECTION: ImageKey.DARK_FIELD,
97
+ }
98
+
99
+ with pytest.raises(TypeError):
100
+ ImageKeyUpgraderTask(
101
+ inputs={
102
+ "data": None,
103
+ "operations": operations,
104
+ },
105
+ ).run()
106
+
107
+ with pytest.raises(TypeError):
108
+ ImageKeyUpgraderTask(
109
+ inputs={
110
+ "data": scan,
111
+ "operations": None,
112
+ },
113
+ ).run()
114
+
115
+ task = ImageKeyUpgraderTask(
116
+ inputs={
117
+ "data": scan,
118
+ "operations": operations,
119
+ },
120
+ )
121
+ task.run()
122
+
123
+ scan = NXtomoScan(scan.master_file, scan.entry)
124
+ assert len(scan.projections) == 0
125
+ assert len(scan.darks) == 20
@@ -0,0 +1,98 @@
1
+ import numpy
2
+ from tomwer.tests.conftest import nxtomo_scan_180 # noqa F811
3
+ from tomwer.core.process.icat.createscreenshots import (
4
+ CreateRawDataScreenshotsTask,
5
+ select_angles,
6
+ )
7
+
8
+
9
+ def test_CreateRawDataScreenshotsTask(nxtomo_scan_180): # noqa F811
10
+ """
11
+ test CreateRawDataScreenshotsTask task
12
+ """
13
+ # test nothing requested
14
+ task = CreateRawDataScreenshotsTask(
15
+ inputs={
16
+ "data": nxtomo_scan_180,
17
+ "raw_projections_required": False,
18
+ "raw_darks_required": False,
19
+ "raw_flats_required": False,
20
+ }
21
+ )
22
+ task.run()
23
+ assert len(task.outputs.screenshots.screenshots) == 0
24
+
25
+ # test only dark requested
26
+ task = CreateRawDataScreenshotsTask(
27
+ inputs={
28
+ "data": nxtomo_scan_180,
29
+ "raw_projections_required": False,
30
+ "raw_darks_required": False,
31
+ "raw_flats_required": True,
32
+ }
33
+ )
34
+ task.run()
35
+ assert len(task.outputs.screenshots.screenshots) == 1
36
+
37
+ # test only flat requested
38
+ task = CreateRawDataScreenshotsTask(
39
+ inputs={
40
+ "data": nxtomo_scan_180,
41
+ "raw_projections_required": False,
42
+ "raw_darks_required": True,
43
+ "raw_flats_required": False,
44
+ }
45
+ )
46
+ task.run()
47
+ assert len(task.outputs.screenshots.screenshots) == 1
48
+
49
+ # test only projection requested
50
+ task = CreateRawDataScreenshotsTask(
51
+ inputs={
52
+ "data": nxtomo_scan_180,
53
+ "raw_projections_required": True,
54
+ "raw_darks_required": False,
55
+ "raw_flats_required": False,
56
+ }
57
+ )
58
+ task.run()
59
+ assert len(task.outputs.screenshots.screenshots) == 2
60
+
61
+ # test all requested
62
+ task = CreateRawDataScreenshotsTask(
63
+ inputs={
64
+ "data": nxtomo_scan_180,
65
+ "raw_projections_required": True,
66
+ "raw_darks_required": True,
67
+ "raw_flats_required": True,
68
+ "raw_projections_each": 10,
69
+ }
70
+ )
71
+ task.run()
72
+ assert len(task.outputs.screenshots.screenshots) == 12
73
+
74
+
75
+ def test_select_angles():
76
+ """test the select_angles function"""
77
+ numpy.testing.assert_allclose(
78
+ select_angles(
79
+ numpy.linspace(start=-20, stop=40, num=201, endpoint=True), each_angle=20
80
+ ),
81
+ numpy.array([-20, 0.1, 19.9, 40]),
82
+ )
83
+
84
+ assert select_angles((), each_angle=20) == ()
85
+ assert select_angles((10,), each_angle=10) == (10,)
86
+ angles = select_angles(
87
+ numpy.linspace(start=0, stop=10, num=400, endpoint=False), each_angle=1
88
+ )
89
+ assert len(angles) == 11
90
+ assert numpy.isclose(angles[0], 0, atol=0.1)
91
+ assert numpy.isclose(angles[-1], 10, atol=0.1)
92
+
93
+
94
+ # def test_CreateRawDataScreenshotsWidgetWorkflow():
95
+ # """
96
+ # test CreateRawDataScreenshotsTask with a MoveScreenshotsToGalleryTask task to make sure the two work well together
97
+ # """
98
+ # raise NotImplementedError