tomwer 1.0.4__py3-none-any.whl → 1.1.0__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 (256) hide show
  1. orangecontrib/tomwer/tutorials/EBS_tomo_listener.ows +39 -0
  2. orangecontrib/tomwer/tutorials/cast_volume.ows +34 -0
  3. orangecontrib/tomwer/tutorials/simple_slice_reconstruction.ows +39 -0
  4. orangecontrib/tomwer/tutorials/simple_volume_local_reconstruction.ows +49 -0
  5. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +59 -0
  6. orangecontrib/tomwer/tutorials/using_saaxis_to_find_cor.ows +44 -0
  7. orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +1 -1
  8. orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +14 -4
  9. orangecontrib/tomwer/widgets/cluster/__init__.py +1 -1
  10. orangecontrib/tomwer/widgets/control/DataListOW.py +12 -5
  11. orangecontrib/tomwer/widgets/control/DataListenerOW.py +18 -9
  12. orangecontrib/tomwer/widgets/control/DataSelectorOW.py +13 -6
  13. orangecontrib/tomwer/widgets/control/DataTransfertOW.py +4 -5
  14. orangecontrib/tomwer/widgets/control/DataValidatorOW.py +8 -4
  15. orangecontrib/tomwer/widgets/control/DataWatcherOW.py +4 -6
  16. orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +49 -62
  17. orangecontrib/tomwer/widgets/control/FilterOW.py +2 -4
  18. orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +93 -0
  19. orangecontrib/tomwer/widgets/control/NXTomomillOW.py +135 -128
  20. orangecontrib/tomwer/widgets/control/NotifierOW.py +31 -7
  21. orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +3 -5
  22. orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +85 -0
  23. orangecontrib/tomwer/widgets/control/VolumeSelector.py +12 -4
  24. orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +11 -7
  25. orangecontrib/tomwer/widgets/control/icons/notification.svg +4 -4
  26. orangecontrib/tomwer/widgets/control/icons/nxtomomill.png +0 -0
  27. orangecontrib/tomwer/widgets/control/icons/nxtomomill.svg +8 -5
  28. orangecontrib/tomwer/widgets/control/icons/tomoobjserie.png +0 -0
  29. orangecontrib/tomwer/widgets/control/icons/tomoobjserie.svg +138 -0
  30. orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +16 -4
  31. orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +100 -0
  32. orangecontrib/tomwer/widgets/edit/icons/image_key_editor.png +0 -0
  33. orangecontrib/tomwer/widgets/edit/icons/image_key_upgrader.png +0 -0
  34. orangecontrib/tomwer/widgets/edit/icons/nx_tomo_editor.png +0 -0
  35. orangecontrib/tomwer/widgets/edit/icons/nx_tomo_editor.svg +123 -0
  36. orangecontrib/tomwer/widgets/edit/test/test_dark_flat_patch.py +21 -1
  37. orangecontrib/tomwer/widgets/edit/test/test_image_key_editor.py +1 -1
  38. orangecontrib/tomwer/widgets/edit/test/test_image_key_upgrader.py +1 -1
  39. orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +25 -0
  40. orangecontrib/tomwer/widgets/other/PythonScriptOW.py +19 -10
  41. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +20 -14
  42. orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +24 -10
  43. orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +26 -21
  44. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +29 -12
  45. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +44 -17
  46. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +28 -18
  47. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +24 -17
  48. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +6 -6
  49. orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +4 -2
  50. orangecontrib/tomwer/widgets/reconstruction/icons/nabu_2d.png +0 -0
  51. orangecontrib/tomwer/widgets/reconstruction/icons/nabu_2d.svg +11 -8
  52. orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +10 -4
  53. orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
  54. orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +69 -0
  55. orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +2 -4
  56. orangecontrib/tomwer/widgets/visualization/icons/nx_tomo_metadata_viewer.png +0 -0
  57. orangecontrib/tomwer/widgets/visualization/icons/nx_tomo_metadata_viewer.svg +105 -0
  58. tomwer/__main__.py +10 -5
  59. tomwer/app/canvas_launcher/config.py +10 -10
  60. tomwer/app/canvas_launcher/mainwindow.py +68 -6
  61. tomwer/app/canvas_launcher/widgetsscheme.py +1 -3
  62. tomwer/app/darkref.py +16 -12
  63. tomwer/app/imagekeyeditor.py +2 -2
  64. tomwer/app/imagekeyupgrader.py +104 -0
  65. tomwer/app/nxtomoeditor.py +103 -0
  66. tomwer/app/rsync.py +1 -1
  67. tomwer/core/cluster/cluster.py +1 -1
  68. tomwer/core/futureobject.py +1 -0
  69. tomwer/core/process/control/datalistener/datalistener.py +7 -1
  70. tomwer/core/process/control/datalistener/rpcserver.py +3 -3
  71. tomwer/core/process/control/datawatcher/datawatcher.py +18 -18
  72. tomwer/core/process/control/datawatcher/datawatcherobserver.py +5 -8
  73. tomwer/core/process/control/datawatcher/datawatcherprocess.py +2 -3
  74. tomwer/core/process/control/datawatcher/edfdwprocess.py +2 -2
  75. tomwer/core/process/control/nxtomomill.py +33 -58
  76. tomwer/core/process/control/scanlist.py +2 -1
  77. tomwer/core/process/control/scanselector.py +7 -0
  78. tomwer/core/process/control/scantransfer.py +9 -18
  79. tomwer/core/process/control/scanvalidator.py +6 -5
  80. tomwer/core/process/control/singletomoobj.py +2 -1
  81. tomwer/core/process/control/timer.py +2 -1
  82. tomwer/core/process/control/tomoobjserie.py +8 -0
  83. tomwer/core/process/control/volumeselector.py +2 -1
  84. tomwer/core/process/control/volumesymlink.py +2 -1
  85. tomwer/core/process/edit/darkflatpatch.py +2 -1
  86. tomwer/core/process/edit/imagekeyeditor.py +4 -3
  87. tomwer/core/process/reconstruction/axis/axis.py +29 -32
  88. tomwer/core/process/reconstruction/axis/mode.py +3 -2
  89. tomwer/core/process/reconstruction/axis/params.py +35 -16
  90. tomwer/core/process/reconstruction/darkref/darkrefs.py +90 -707
  91. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +44 -16
  92. tomwer/core/process/reconstruction/darkref/params.py +62 -67
  93. tomwer/core/process/reconstruction/lamino/tofu.py +1 -1
  94. tomwer/core/process/reconstruction/nabu/castvolume.py +21 -26
  95. tomwer/core/process/reconstruction/nabu/nabucommon.py +36 -38
  96. tomwer/core/process/reconstruction/nabu/nabuscores.py +28 -13
  97. tomwer/core/process/reconstruction/nabu/nabuslices.py +41 -14
  98. tomwer/core/process/reconstruction/nabu/nabuvolume.py +21 -12
  99. tomwer/core/process/reconstruction/nabu/utils.py +12 -1
  100. tomwer/core/process/reconstruction/normalization/normalization.py +9 -8
  101. tomwer/core/process/reconstruction/saaxis/saaxis.py +46 -20
  102. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +38 -12
  103. tomwer/core/process/reconstruction/test/__init__.py +0 -39
  104. tomwer/core/process/reconstruction/test/test_axis_params.py +25 -3
  105. tomwer/core/process/reconstruction/test/test_darkref_copy.py +117 -1
  106. tomwer/core/process/script/python.py +16 -12
  107. tomwer/core/process/task.py +3 -7
  108. tomwer/core/process/test/test_axis.py +1 -1
  109. tomwer/core/process/test/test_dark_and_flat.py +41 -111
  110. tomwer/core/process/test/test_data_listener.py +0 -29
  111. tomwer/core/process/test/test_data_transfer.py +10 -14
  112. tomwer/core/process/test/test_nabu.py +1 -1
  113. tomwer/core/process/test/test_normalization.py +1 -1
  114. tomwer/core/process/visualization/liveslice.py +6 -0
  115. tomwer/core/scan/blissscan.py +37 -2
  116. tomwer/core/scan/edfscan.py +14 -4
  117. tomwer/core/scan/hdf5scan.py +10 -4
  118. tomwer/core/scan/scanbase.py +35 -29
  119. tomwer/core/scan/scanfactory.py +3 -17
  120. tomwer/core/scan/test/test_h5.py +1 -1
  121. tomwer/core/scan/test/test_process_registration.py +0 -11
  122. tomwer/core/scan/test/test_scan.py +32 -30
  123. tomwer/core/settings.py +2 -2
  124. tomwer/core/test/test_utils.py +1 -1
  125. tomwer/core/tomwer_object.py +19 -0
  126. tomwer/core/utils/__init__.py +0 -45
  127. tomwer/core/utils/char.py +2 -0
  128. tomwer/core/utils/gpu.py +5 -5
  129. tomwer/core/utils/nxtomoutils.py +2 -2
  130. tomwer/core/utils/scanutils.py +50 -0
  131. tomwer/core/utils/volumeutils.py +13 -0
  132. tomwer/core/volume/edfvolume.py +4 -0
  133. tomwer/core/volume/hdf5volume.py +4 -0
  134. tomwer/core/volume/jp2kvolume.py +4 -0
  135. tomwer/core/volume/rawvolume.py +4 -0
  136. tomwer/core/volume/tiffvolume.py +4 -0
  137. tomwer/core/volume/volumebase.py +19 -12
  138. tomwer/core/volume/volumefactory.py +20 -1
  139. tomwer/gui/cluster/slurm.py +1 -1
  140. tomwer/gui/cluster/test/test_cluster.py +2 -2
  141. tomwer/gui/control/datalist.py +109 -34
  142. tomwer/gui/control/datatransfert.py +1 -1
  143. tomwer/gui/control/datawatcher/datawatcher.py +23 -13
  144. tomwer/gui/control/datawatcher/datawatcherobserver.py +1 -1
  145. tomwer/gui/control/observations.py +0 -3
  146. tomwer/gui/control/selectorwidgetbase.py +42 -11
  147. tomwer/gui/control/serie/seriecreator.py +967 -0
  148. tomwer/{web/__init__.py → gui/control/serie/seriewaiter.py} +5 -7
  149. tomwer/gui/control/singletomoobj.py +15 -3
  150. tomwer/gui/control/test/test_datalist.py +1 -1
  151. tomwer/gui/control/test/test_datalistener.py +1 -1
  152. tomwer/gui/control/test/test_inputwidget.py +1 -1
  153. tomwer/gui/control/test/test_process_manager.py +1 -13
  154. tomwer/gui/control/test/test_scanselector.py +1 -1
  155. tomwer/gui/control/test/test_scanvalidator.py +1 -1
  156. tomwer/gui/control/test/test_single_tomo_obj.py +1 -1
  157. tomwer/gui/control/test/test_volume_dialog.py +19 -7
  158. tomwer/gui/control/test/test_volumeselector.py +4 -4
  159. tomwer/gui/debugtools/datasetgenerator.py +1 -8
  160. tomwer/gui/edit/dkrfpatch.py +2 -2
  161. tomwer/gui/edit/imagekeyeditor.py +12 -9
  162. tomwer/gui/edit/nxtomoeditor.py +475 -0
  163. tomwer/gui/edit/test/test_dkrf_patch.py +2 -14
  164. tomwer/gui/edit/test/test_image_key_editor.py +2 -2
  165. tomwer/gui/edit/test/test_nx_editor.py +155 -0
  166. tomwer/gui/qfolderdialog.py +11 -0
  167. tomwer/gui/reconstruction/axis/CompareImages.py +27 -29
  168. tomwer/gui/reconstruction/axis/axis.py +2 -0
  169. tomwer/gui/reconstruction/axis/radioaxis.py +67 -11
  170. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +7 -9
  171. tomwer/gui/reconstruction/darkref/darkrefwidget.py +22 -24
  172. tomwer/gui/reconstruction/lamino/tofu/projections.py +1 -1
  173. tomwer/gui/reconstruction/lamino/tofu/tofu.py +3 -3
  174. tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +4 -4
  175. tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +10 -4
  176. tomwer/gui/reconstruction/nabu/castvolume.py +80 -11
  177. tomwer/gui/reconstruction/nabu/check.py +1 -1
  178. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +352 -0
  179. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +0 -9
  180. tomwer/gui/reconstruction/nabu/nabuconfig/output.py +1 -1
  181. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +18 -19
  182. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +30 -7
  183. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +26 -13
  184. tomwer/gui/reconstruction/nabu/slices.py +10 -2
  185. tomwer/gui/reconstruction/nabu/slurm.py +1 -1
  186. tomwer/gui/reconstruction/nabu/volume.py +13 -7
  187. tomwer/gui/reconstruction/normalization/intensity.py +1 -1
  188. tomwer/gui/reconstruction/saaxis/corrangeselector.py +10 -34
  189. tomwer/gui/reconstruction/saaxis/saaxis.py +11 -6
  190. tomwer/gui/reconstruction/saaxis/sliceselector.py +11 -26
  191. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +13 -8
  192. tomwer/gui/reconstruction/scores/scoreplot.py +67 -61
  193. tomwer/gui/reconstruction/test/test_axis.py +2 -2
  194. tomwer/gui/reconstruction/test/test_lamino.py +2 -2
  195. tomwer/gui/reconstruction/test/test_nabu.py +14 -1
  196. tomwer/gui/reconstruction/test/test_saaxis.py +8 -17
  197. tomwer/gui/reconstruction/test/test_sadeltabeta.py +7 -13
  198. tomwer/gui/stackplot.py +11 -28
  199. tomwer/gui/test/test_axis_gui.py +4 -4
  200. tomwer/gui/test/test_qfolder_dialog.py +12 -0
  201. tomwer/gui/utils/inputwidget.py +42 -21
  202. tomwer/gui/utils/lineselector/lineselector.py +13 -21
  203. tomwer/gui/utils/scandescription.py +2 -4
  204. tomwer/gui/utils/slider.py +1 -102
  205. tomwer/gui/utils/unitsystem.py +48 -11
  206. tomwer/gui/visualization/dataviewer.py +24 -17
  207. tomwer/gui/visualization/diffviewer/diffviewer.py +2 -11
  208. tomwer/gui/visualization/nxtomometadata.py +21 -0
  209. tomwer/gui/visualization/scanoverview.py +0 -1
  210. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +72 -0
  211. tomwer/gui/visualization/test/test_stacks.py +1 -1
  212. tomwer/gui/visualization/tomoobjoverview.py +49 -0
  213. tomwer/gui/visualization/volumeoverview.py +64 -0
  214. tomwer/gui/visualization/volumeviewer.py +1 -1
  215. tomwer/resources/gui/icons/multi-document-save.png +0 -0
  216. tomwer/resources/gui/icons/multi-document-save.svg +101 -0
  217. tomwer/resources/gui/illustrations/ctf_z1.png +0 -0
  218. tomwer/resources/gui/illustrations/ctf_z1.svg +471 -0
  219. tomwer/synctools/datalistener.py +5 -1
  220. tomwer/synctools/imageloaderthread.py +2 -2
  221. tomwer/synctools/stacks/edit/imagekeyeditor.py +1 -1
  222. tomwer/synctools/stacks/processingstack.py +2 -2
  223. tomwer/synctools/stacks/reconstruction/castvolume.py +1 -0
  224. tomwer/synctools/stacks/reconstruction/lamino.py +1 -3
  225. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +0 -2
  226. tomwer/synctools/test/test_darkRefs.py +32 -149
  227. tomwer/synctools/test/test_foldertransfer.py +1 -1
  228. tomwer/synctools/test/test_scanstages.py +2 -2
  229. tomwer/tests/__init__.py +0 -0
  230. tomwer/tests/conftest.py +51 -0
  231. tomwer/{test → tests}/test_scripts.py +1 -1
  232. tomwer/tests/test_utils.py +10 -0
  233. tomwer/{test → tests}/utils/utilstest.py +0 -11
  234. tomwer/version.py +3 -3
  235. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/METADATA +14 -16
  236. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/RECORD +245 -217
  237. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/WHEEL +1 -1
  238. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/entry_points.txt +6 -0
  239. orangecontrib/tomwer/setup.py +0 -45
  240. orangecontrib/tomwer/widgets/setup.py +0 -49
  241. tomwer/app/process.py +0 -153
  242. tomwer/core/process/reconstruction/nabu/slurm.py +0 -36
  243. tomwer/core/process/reconstruction/utils/nabu_slice_exec.py +0 -10
  244. tomwer/core/utils/laminoutils.py +0 -80
  245. tomwer/gui/utils/lineselector/lineselection.py +0 -76
  246. tomwer/setup.py +0 -52
  247. tomwer/web/client.py +0 -43
  248. tomwer/web/config.py +0 -36
  249. tomwer/web/test/test_graylog_connection.py +0 -59
  250. {tomwer/test → orangecontrib/tomwer/tutorials}/__init__.py +0 -0
  251. /tomwer/{web/test → gui/control/serie}/__init__.py +0 -0
  252. /tomwer/{test → tests}/utils/__init__.py +0 -0
  253. /tomwer-1.0.4-py3.8-nspkg.pth → /tomwer-1.1.0-py3.9-nspkg.pth +0 -0
  254. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/LICENSE +0 -0
  255. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/namespace_packages.txt +0 -0
  256. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/top_level.txt +0 -0
@@ -33,15 +33,19 @@ __date__ = "17/08/2021"
33
33
 
34
34
 
35
35
  import os
36
+ import logging
37
+ import tempfile
36
38
  from typing import Union
37
39
  from silx.io.url import DataUrl
38
40
  from silx.io.dictdump import dicttoh5
39
41
  from tomoscan.io import HDF5File
40
- import logging
42
+ from tomoscan.esrf.scan.utils import cwd_context
43
+ from tomoscan.framereducerbase import REDUCER_TARGET
41
44
  from tomwer.core.process.reconstruction.darkref.darkrefs import DarkRefs
42
45
  from tomwer.core.scan.scanbase import TomwerScanBase
43
- from tomoscan.esrf.scan.utils import get_data
46
+ from tomwer.core.utils.scanutils import data_identifier_to_scan
44
47
  from tomoscan.esrf.scan.utils import copy_h5_dict_darks_to, copy_h5_dict_flats_to
48
+ from silx.io.dictdump import h5todict
45
49
 
46
50
  logger = logging.getLogger(__name__)
47
51
 
@@ -76,11 +80,7 @@ class DarkRefsCopy(DarkRefs):
76
80
  self._mode_auto = inputs.get("mode_auto", True)
77
81
  if "savedir" in inputs:
78
82
  raise KeyError("savedir is not a valid key. Use save_dir")
79
- self._savedir = inputs.get("save_dir", None)
80
- if self._savedir is None:
81
- raise KeyError(
82
- "save_dir is expected (where the ref and dark file should be saved)"
83
- )
83
+ self._savedir = inputs.get("save_dir", tempfile.mkdtemp())
84
84
  self._save_file = self.get_save_file(self._savedir)
85
85
  self._darks_url = self.get_darks_url(self._savedir)
86
86
  self._flats_url = self.get_flats_url(self._savedir)
@@ -127,10 +127,42 @@ class DarkRefsCopy(DarkRefs):
127
127
  self._processOnlyDkRf = False
128
128
  self._processOnlyCopy = value
129
129
 
130
+ @staticmethod
131
+ def get_reduced_frame_data(
132
+ url: DataUrl, reduced_target: REDUCER_TARGET, check_for_reduced_key: bool = True
133
+ ) -> tuple:
134
+ """
135
+ :param Data url: url expected to contain the dict with one key per serie of reduced frame
136
+ :param REDUCER_TARGET reduced_target: what we are looking for (used when check_for_reduced_key is set to True)
137
+ :param bool check_for_reduced_key: if True then if the dict contains the given key then return the value of this key instead
138
+ of the loaded dict. Used as a user friendly feature to be able to load dict when upper data path
139
+ is provided instead of the 'darks' or 'flats' one.
140
+ :return: data, metadata
141
+ :rtype: tuple of two dicts
142
+ """
143
+ reduced_target = REDUCER_TARGET.from_value(reduced_target)
144
+
145
+ with cwd_context(url.file_path()):
146
+ try:
147
+ reduced_info_dict = h5todict(
148
+ h5file=url.file_path(),
149
+ path=url.data_path(),
150
+ )
151
+ except Exception as e:
152
+ logger.error(e)
153
+ return None
154
+ else:
155
+ if check_for_reduced_key and reduced_target.value in reduced_info_dict:
156
+ return reduced_info_dict[reduced_target.value]
157
+ else:
158
+ return reduced_info_dict
159
+
130
160
  @staticmethod
131
161
  def save_flats_to_be_copied(save_dir, data: Union[DataUrl, dict]):
132
162
  if isinstance(data, DataUrl):
133
- data = get_data(data)
163
+ data = DarkRefsCopy.get_reduced_frame_data(url=data, reduced_target="flats")
164
+ if data is None:
165
+ return
134
166
  flat_url = DarkRefsCopy.get_flats_url(save_dir)
135
167
  dicttoh5(
136
168
  data,
@@ -143,7 +175,9 @@ class DarkRefsCopy(DarkRefs):
143
175
  @staticmethod
144
176
  def save_darks_to_be_copied(save_dir, data: Union[DataUrl, dict]):
145
177
  if isinstance(data, DataUrl):
146
- data = get_data(data)
178
+ data = DarkRefsCopy.get_reduced_frame_data(url=data, reduced_target="darks")
179
+ if data is None:
180
+ return
147
181
  dark_url = DarkRefsCopy.get_darks_url(save_dir)
148
182
  dicttoh5(
149
183
  data,
@@ -216,7 +250,7 @@ class DarkRefsCopy(DarkRefs):
216
250
  * if the scan has no ref files and refCopy has some register. Will
217
251
  create a copy of those, normalized from srCurrent (for flat field)
218
252
  """
219
- scan = self.inputs.data
253
+ scan = data_identifier_to_scan(self.inputs.data)
220
254
  if not isinstance(scan, (type(None), TomwerScanBase, dict)):
221
255
  raise TypeError(
222
256
  f"self.inputs.data is expected to be an instance "
@@ -322,9 +356,3 @@ class DarkRefsCopy(DarkRefs):
322
356
 
323
357
  def set_darkHST_prefix(self, prefix):
324
358
  self._darkHstPrefix = prefix
325
-
326
- def clear_ref(self):
327
- if self._flat_save_file is not None:
328
- os.remove(self._flat_save_file)
329
- if self._dark_save_file is not None:
330
- os.remove(self._dark_save_file)
@@ -36,6 +36,7 @@ from tomwer.core.process.reconstruction.darkref.settings import (
36
36
  )
37
37
  from tomwer.core.process.reconstruction.paramsbase import _ReconsParam
38
38
  from tomwer.core.utils.deprecation import deprecated
39
+ from tomoscan.framereducerbase import ReduceMethod
39
40
 
40
41
 
41
42
  # TODO: those classes (when, method) should be linked / embedded in the DarkRef
@@ -47,21 +48,19 @@ class When(_Enum):
47
48
  after = (2,)
48
49
 
49
50
 
50
- @enum.unique
51
- class Method(_Enum):
52
- none = (0,)
53
- average = (1,)
54
- median = 2
55
- first = 10
56
- last = 11
57
-
58
- @classmethod
59
- def from_value(cls, value):
60
- if isinstance(value, str):
61
- for m in Method:
62
- if value.lower() == m.name.lower():
63
- return m
64
- return super().from_value(value)
51
+ def _from_value_reduce_method_backward_compatibility(value) -> ReduceMethod:
52
+ if value in ("none", 0, (0,)):
53
+ return ReduceMethod.NONE
54
+ elif value in ("average", 1, (1,)):
55
+ return ReduceMethod.MEAN
56
+ elif value in ("median", 2, (2,)):
57
+ return ReduceMethod.MEDIAN
58
+ elif value in ("first", 10, (10,)):
59
+ return ReduceMethod.FIRST
60
+ elif value in ("last", 11, (11,)):
61
+ return ReduceMethod.FIRST
62
+ else:
63
+ return ReduceMethod.from_value(value)
65
64
 
66
65
 
67
66
  class DKRFRP(_ReconsParam):
@@ -70,14 +69,14 @@ class DKRFRP(_ReconsParam):
70
69
  def __init__(self):
71
70
  _ReconsParam.__init__(self)
72
71
  self.__do_when = When.before
73
- self.__dark_calc = Method.average
72
+ self.__dark_calc = ReduceMethod.MEAN
74
73
  self.__overwrite_dark = False
75
74
  self.__remove_dark = False
76
75
  self.__dark_pattern = "darkend[0-9]{3,4}"
77
- self.__ref_calc = Method.median
76
+ self.__flat_calc = ReduceMethod.MEDIAN
78
77
  self.__overwrite_flat = False
79
- self.__remove_ref = False
80
- self.__ref_pattern = "ref*.*[0-9]{3,4}_[0-9]{3,4}"
78
+ self.__remove_flats = False
79
+ self.__flat_pattern = "ref*.*[0-9]{3,4}_[0-9]{3,4}"
81
80
  self.__dark_prefix = DARKHST_PREFIX
82
81
  self.__ref_prefix = REFHST_PREFIX
83
82
 
@@ -87,10 +86,10 @@ class DKRFRP(_ReconsParam):
87
86
  "DARKOVE": self.__class__.overwrite_dark,
88
87
  "DARKRMV": self.__class__.remove_dark,
89
88
  "DKFILE": self.__class__.dark_pattern,
90
- "REFSCAL": self.__class__.ref_calc_method,
89
+ "REFSCAL": self.__class__.flat_calc_method,
91
90
  "REFSOVE": self.__class__.overwrite_flat,
92
- "REFSRMV": self.__class__.remove_ref,
93
- "RFFILE": self.__class__.ref_pattern,
91
+ "REFSRMV": self.__class__.remove_raw_flats,
92
+ "RFFILE": self.__class__.flat_pattern,
94
93
  }
95
94
 
96
95
  @property
@@ -114,11 +113,8 @@ class DKRFRP(_ReconsParam):
114
113
 
115
114
  @dark_calc_method.setter
116
115
  def dark_calc_method(self, method):
117
- assert isinstance(method, (int, Method, str))
118
- if isinstance(method, str):
119
- _dark_calc = getattr(Method, method.lower())
120
- else:
121
- _dark_calc = Method(method)
116
+ assert isinstance(method, (int, ReduceMethod, str))
117
+ _dark_calc = _from_value_reduce_method_backward_compatibility(method)
122
118
 
123
119
  if self.__dark_calc != _dark_calc:
124
120
  self.__dark_calc = _dark_calc
@@ -163,19 +159,16 @@ class DKRFRP(_ReconsParam):
163
159
  self.changed()
164
160
 
165
161
  @property
166
- def ref_calc_method(self):
162
+ def flat_calc_method(self):
167
163
  """Dark calculation method (None, Average, Median)"""
168
- return self.__ref_calc
169
-
170
- @ref_calc_method.setter
171
- def ref_calc_method(self, method):
172
- assert isinstance(method, (int, Method, str))
173
- if isinstance(method, str):
174
- _ref_calc = getattr(Method, method.lower())
175
- else:
176
- _ref_calc = Method(method)
177
- if self.__ref_calc != _ref_calc:
178
- self.__ref_calc = _ref_calc
164
+ return self.__flat_calc
165
+
166
+ @flat_calc_method.setter
167
+ def flat_calc_method(self, method):
168
+ assert isinstance(method, (int, ReduceMethod, str))
169
+ _ref_calc = _from_value_reduce_method_backward_compatibility(method)
170
+ if self.__flat_calc != _ref_calc:
171
+ self.__flat_calc = _ref_calc
179
172
  self.changed()
180
173
 
181
174
  @property
@@ -202,42 +195,44 @@ class DKRFRP(_ReconsParam):
202
195
  self.changed()
203
196
 
204
197
  @property
205
- def remove_ref(self):
206
- """Remove original ref files when done"""
207
- return self.__remove_ref
198
+ def remove_raw_flats(self):
199
+ """Remove original flat / ref files when done (for EDF only)"""
200
+ return self.__remove_flats
208
201
 
209
- @remove_ref.setter
210
- def remove_ref(self, remove):
202
+ @remove_raw_flats.setter
203
+ def remove_raw_flats(self, remove):
211
204
  # TODO: float should be removed, but this is a legacy from fastomo3
212
205
  assert isinstance(remove, (int, bool, float))
213
- _remove_ref = remove
214
- if self.__remove_ref != _remove_ref:
215
- self.__remove_ref = _remove_ref
206
+ _remove_flats = remove
207
+ if self.__remove_flats != _remove_flats:
208
+ self.__remove_flats = _remove_flats
216
209
  self.changed()
217
210
 
218
211
  @property
219
- def ref_pattern(self):
220
- """File pattern to detect references"""
221
- return self.__ref_pattern
222
-
223
- @ref_pattern.setter
224
- def ref_pattern(self, pattern):
225
- if pattern != self.__ref_pattern:
226
- self.__ref_pattern = pattern
212
+ def flat_pattern(self):
213
+ """File pattern to detect EDF flats files"""
214
+ return self.__flat_pattern
215
+
216
+ @flat_pattern.setter
217
+ def flat_pattern(self, pattern):
218
+ if pattern != self.__flat_pattern:
219
+ self.__flat_pattern = pattern
227
220
  self.changed()
228
221
 
229
222
  @property
230
- def ref_prefix(self):
223
+ def flat_prefix(self):
224
+ """flat prefix for EDF"""
231
225
  return self.__ref_prefix
232
226
 
233
- @ref_prefix.setter
234
- def ref_prefix(self, prefix):
227
+ @flat_prefix.setter
228
+ def flat_prefix(self, prefix):
235
229
  if prefix != self.__ref_prefix:
236
230
  self.__ref_prefix = prefix
237
231
  self.changed()
238
232
 
239
233
  @property
240
234
  def dark_prefix(self):
235
+ """dark prefix for EDF"""
241
236
  return self.__dark_prefix
242
237
 
243
238
  @dark_prefix.setter
@@ -247,7 +242,7 @@ class DKRFRP(_ReconsParam):
247
242
  self.changed()
248
243
 
249
244
  def _set_remove_opt(self, rm):
250
- self.remove_ref = rm
245
+ self.remove_raw_flats = rm
251
246
  self.remove_dark = rm
252
247
 
253
248
  def _set_skip_if_exist(self, skip):
@@ -257,14 +252,14 @@ class DKRFRP(_ReconsParam):
257
252
  def to_dict(self):
258
253
  _dict = {
259
254
  "DOWHEN": self.do_when.name,
260
- "DARKCAL": self.dark_calc_method.name.split(".")[-1].title(),
255
+ "DARKCAL": self.dark_calc_method.value,
261
256
  "DARKOVE": int(self.overwrite_dark),
262
257
  "DARKRMV": int(self.remove_dark),
263
258
  "DKFILE": self.dark_pattern,
264
- "REFSCAL": self.ref_calc_method.name.split(".")[-1].title(),
259
+ "REFSCAL": self.flat_calc_method.value,
265
260
  "REFSOVE": int(self.overwrite_flat),
266
- "REFSRMV": int(self.remove_ref),
267
- "RFFILE": self.ref_pattern,
261
+ "REFSRMV": int(self.remove_raw_flats),
262
+ "RFFILE": self.flat_pattern,
268
263
  }
269
264
  _dict.update(self.unmanaged_params)
270
265
  return _dict
@@ -278,11 +273,11 @@ class DKRFRP(_ReconsParam):
278
273
  def load_from_dict(self, _dict):
279
274
  self._load_unmanaged_params(_dict=_dict)
280
275
  self.do_when = getattr(When, _dict["DOWHEN"])
281
- self.dark_calc_method = getattr(Method, _dict["DARKCAL"].lower())
276
+ self.dark_calc_method = _dict["DARKCAL"]
282
277
  self.overwrite_dark = _dict["DARKOVE"]
283
278
  self.remove_dark = _dict["DARKRMV"]
284
279
  self.dark_pattern = _dict["DKFILE"]
285
- self.ref_calc_method = getattr(Method, _dict["REFSCAL"].lower())
280
+ self.flat_calc_method = _dict["REFSCAL"]
286
281
  self.overwrite_flat = _dict["REFSOVE"]
287
- self.remove_ref = _dict["REFSRMV"]
288
- self.ref_pattern = _dict["RFFILE"]
282
+ self.remove_raw_flats = _dict["REFSRMV"]
283
+ self.flat_pattern = _dict["RFFILE"]
@@ -882,7 +882,7 @@ class LaminoReconstruction(Task, input_names=("data",), output_names=("data",)):
882
882
  )
883
883
 
884
884
  if res is False:
885
- logger.error("Reconstruction of", _scan.path, "failed")
885
+ logger.error(f"Reconstruction of {_scan.path} failed")
886
886
  if self._return_dict:
887
887
  self.outputs.data = _scan.to_dict()
888
888
  else:
@@ -32,7 +32,6 @@ __date__ = "15/12/2021"
32
32
 
33
33
 
34
34
  import os
35
- import inspect
36
35
  from processview.core.superviseprocess import SuperviseProcess
37
36
  from tomwer.core.cluster.cluster import SlurmClusterConfiguration
38
37
  from tomwer.core.process.reconstruction.nabu import settings
@@ -54,6 +53,7 @@ from tomwer.core.futureobject import FutureTomwerObject
54
53
  from tomwer.core.utils.slurm import get_slurm_script_name
55
54
  from tomwer.core.volume.volumefactory import VolumeFactory
56
55
  from tomwer.core.volume.volumebase import TomwerVolumeBase
56
+ from tomwer.core.utils.volumeutils import volume_identifier_to_volume
57
57
  from sluurp.job import SBatchScriptJob
58
58
  from sluurp.executor import submit as submit_to_slurm_cluster
59
59
 
@@ -97,7 +97,7 @@ class CastVolumeTask(
97
97
  self._cluster_config = None
98
98
 
99
99
  def run(self):
100
- input_volume = self.inputs.volume
100
+ input_volume = volume_identifier_to_volume(self.inputs.volume)
101
101
  if not isinstance(input_volume, VolumeBase):
102
102
  raise TypeError(
103
103
  f"input_volume is a {type(input_volume)} when {VolumeBase} expected"
@@ -165,36 +165,27 @@ class CastVolumeTask(
165
165
 
166
166
  # run volume cast locally
167
167
  if self._cluster_config is None:
168
- cast_params = {
169
- "input_volume": input_volume,
170
- "output_volume": output_volume,
171
- "output_data_type": output_data_type,
172
- "data_min": data_min,
173
- "data_max": data_max,
174
- "scan": scan,
175
- "rescale_min_percentile": rescale_min_percentile,
176
- "rescale_max_percentile": rescale_max_percentile,
177
- }
178
- if "overwrite" in inspect.signature(_nabu_cast_volume).parameters:
179
- cast_params["overwrite"] = overwrite
180
168
  try:
181
- volume = _nabu_cast_volume(**cast_params)
169
+ _nabu_cast_volume(
170
+ input_volume=input_volume,
171
+ output_volume=output_volume,
172
+ output_data_type=output_data_type,
173
+ data_min=data_min,
174
+ data_max=data_max,
175
+ scan=scan,
176
+ rescale_min_percentile=rescale_min_percentile,
177
+ rescale_max_percentile=rescale_max_percentile,
178
+ save=True,
179
+ store=False,
180
+ )
182
181
  except Exception as e:
183
182
  mess = f"volume cast of {str(input_volume)} failed. Reason is {str(e)}"
184
183
  _logger.processFailed(mess)
185
184
  state = DatasetState.FAILED
186
-
187
185
  else:
188
- try:
189
- volume.save()
190
- except Exception as e:
191
- mess = f"fail to save cast volume {str(output_volume)}. Reason is {str(e)}"
192
- _logger.processFailed(mess)
193
- state = DatasetState.FAILED
194
- else:
195
- mess = f"volume cast of {str(input_volume)} succeed"
196
- _logger.processSucceed(mess)
197
- state = DatasetState.SUCCEED
186
+ mess = f"volume cast of {str(input_volume)} succeed"
187
+ _logger.processSucceed(mess)
188
+ state = DatasetState.SUCCEED
198
189
 
199
190
  ProcessManager().notify_dataset_state(
200
191
  dataset=input_volume,
@@ -204,6 +195,10 @@ class CastVolumeTask(
204
195
  )
205
196
  self.outputs.future_tomo_obj = None
206
197
  self.outputs.volume = output_volume
198
+ if scan is not None:
199
+ scan.cast_volume = output_volume.get_identifier()
200
+ else:
201
+ input_volume.cast_volume = output_volume.get_identifier()
207
202
  # run volume cast remotly
208
203
  else:
209
204
 
@@ -42,6 +42,7 @@ from tomwer.core.process.reconstruction.nabu.utils import (
42
42
  _NabuPhaseMethod,
43
43
  nabu_std_err_has_error,
44
44
  )
45
+ from tomwer.core.utils.scanutils import format_output_location
45
46
  from tomwer.core.scan.edfscan import EDFTomoScan
46
47
  from tomwer.core.scan.hdf5scan import HDF5TomoScan
47
48
  from tomwer.core.scan.scanbase import TomwerScanBase
@@ -65,13 +66,20 @@ import numpy
65
66
 
66
67
  _logger = logging.getLogger(__name__)
67
68
  try:
68
- from nabu.pipeline.fullfield.local_reconstruction import ( # noqa F401
69
- ChunkedReconstructor,
69
+ from nabu.pipeline.fullfield.reconstruction import ( # noqa F401
70
+ FullFieldReconstructor,
70
71
  )
71
72
  except (ImportError, OSError) as e:
72
- # import of cufft library can bring an OSError if cuda not install
73
- _logger.error(e)
74
- has_nabu = False
73
+ try:
74
+ from nabu.pipeline.fullfield.local_reconstruction import ( # noqa F401
75
+ ChunkedReconstructor,
76
+ )
77
+ except (ImportError, OSError):
78
+ # import of cufft library can bring an OSError if cuda not install
79
+ _logger.error(e)
80
+ has_nabu = False
81
+ else:
82
+ has_nabu = True
75
83
  else:
76
84
  has_nabu = True
77
85
 
@@ -445,28 +453,45 @@ class _NabuBaseReconstructor:
445
453
  """
446
454
  # handle phase
447
455
  pag = False
456
+ ctf = False
448
457
  db = None
449
458
  if "phase" in config:
450
- if (
459
+ pag = (
451
460
  "method" in config["phase"]
452
461
  and config["phase"]["method"] == _NabuPhaseMethod.PAGANIN.value
453
- ):
454
- pag = True
462
+ )
463
+ ctf = (
464
+ "method" in config["phase"]
465
+ and config["phase"]["method"] == _NabuPhaseMethod.CTF.value
466
+ )
467
+ if pag or ctf:
455
468
  if "delta_beta" in config["phase"]:
469
+ if not numpy.isscalar(config["phase"]["delta_beta"]):
470
+ if len(config["phase"]["delta_beta"]) > 1:
471
+ raise ValueError(
472
+ "expects at most one value for 'delta_beta'"
473
+ )
474
+ else:
475
+ config["phase"]["delta_beta"] = config["phase"][
476
+ "delta_beta"
477
+ ][0]
456
478
  db = round(float(config["phase"]["delta_beta"]))
457
479
  # handle output
458
480
  if "output" in config:
459
- _file_name = self._get_file_basename_reconstruction(pag=pag, db=db)
481
+ _file_name = self._get_file_basename_reconstruction(pag=pag, db=db, ctf=ctf)
460
482
  config["output"]["file_prefix"] = _file_name
461
483
  location = config["output"].get("location", None)
462
484
  if location not in ("", None):
463
- location = self.format_output_location(location, scan=self.scan)
485
+ location = format_output_location(location, scan=self.scan)
464
486
  # if user specify the location
465
487
  if not os.path.isdir(config["output"]["location"]):
466
488
  os.makedirs(location)
467
489
  else:
468
490
  # otherwise default location will be the data root level
469
491
  location = self.scan.path
492
+ # add reconstruction path to the list. scan `reconstruction_paths` register all the existing path where
493
+ # reconstruction are saved in order to be able to browse them all
494
+ self.scan.add_reconstruction_path(location)
470
495
  config["output"]["location"] = location
471
496
  # handle preproc
472
497
  if "preproc" not in config:
@@ -545,37 +570,10 @@ class _NabuBaseReconstructor:
545
570
 
546
571
  return config
547
572
 
548
- def _get_file_basename_reconstruction(self, pag, db):
573
+ def _get_file_basename_reconstruction(self, pag, db, ctf):
549
574
  """return created file base name"""
550
575
  raise NotImplementedError("Base class")
551
576
 
552
- @staticmethod
553
- def format_output_location(location, scan: TomwerScanBase):
554
- """
555
- format possible keys from the location like {scan_dir} or {scan_path}
556
-
557
- :param location:
558
- :param scan:
559
- :return:
560
- """
561
- if scan is None:
562
- _logger.warning("scan is !none, enable to format the nabu output location")
563
-
564
- keywords = {
565
- "scan_dir_name": scan.scan_dir_name(),
566
- "scan_basename": scan.scan_basename(),
567
- "scan_parent_dir_basename": scan.scan_parent_dir_basename(),
568
- }
569
- for keyword, value in keywords.items():
570
- if value is None:
571
- continue
572
- try:
573
- location = location.format(**{keyword: value})
574
- except KeyError:
575
- # then this mean scan_dir has not been provided
576
- pass
577
- return location
578
-
579
577
 
580
578
  def dump_normalization_array_for_nabu(
581
579
  scan: TomwerScanBase, output_file: str, array: Union[numpy.ndarray, float, int]
@@ -31,14 +31,20 @@ __authors__ = [
31
31
  __license__ = "MIT"
32
32
  __date__ = "28/10/2021"
33
33
 
34
-
35
34
  try:
36
- from nabu.pipeline.fullfield.local_reconstruction import ( # noqa F401
37
- ChunkedReconstructor,
35
+ from nabu.pipeline.fullfield.reconstruction import ( # noqa F401
36
+ FullFieldReconstructor,
38
37
  )
39
38
  except (ImportError, OSError):
40
- # import of cufft library can bring an OSError if cuda not install
41
- has_nabu = False
39
+ try:
40
+ from nabu.pipeline.fullfield.local_reconstruction import ( # noqa F401
41
+ ChunkedReconstructor,
42
+ )
43
+ except (ImportError, OSError):
44
+ # import of cufft library can bring an OSError if cuda not install
45
+ has_nabu = False
46
+ else:
47
+ has_nabu = True
42
48
  else:
43
49
  has_nabu = True
44
50
  from typing import Iterable, Optional, Union
@@ -229,18 +235,24 @@ class _Reconstructor(_NabuBaseReconstructor):
229
235
  - create the output directory if does not exist
230
236
  """
231
237
  pag = False
238
+ ctf = False
232
239
  db = None
233
240
  if "phase" in _config:
234
- if "method" in _config["phase"] and _config["phase"]["method"] not in (
235
- "",
236
- utils._NabuPhaseMethod.NONE.value,
237
- ):
241
+ phase_method = _config["phase"].get("method", "").lower()
242
+ if phase_method in ("pag", "paganin"):
238
243
  pag = True
239
- if "delta_beta" in _config["phase"]:
240
- db = round(float(_config["phase"]["delta_beta"]))
244
+ elif phase_method in ("ctf",):
245
+ ctf = True
246
+
247
+ if "delta_beta" in _config["phase"]:
248
+ db = round(float(_config["phase"]["delta_beta"]))
241
249
  if "output" in _config:
242
250
  _file_name = SingleSliceRunner.get_file_basename_reconstruction(
243
- scan=self.scan, slice_index=self.slice_index, pag=pag, db=db
251
+ scan=self.scan,
252
+ slice_index=self.slice_index,
253
+ pag=pag,
254
+ db=db,
255
+ ctf=ctf,
244
256
  )
245
257
  _config["output"]["file_prefix"] = "cor_{}_{}".format(_file_name, cor)
246
258
  if _config["output"]["location"] not in ("", None):
@@ -250,7 +262,10 @@ class _Reconstructor(_NabuBaseReconstructor):
250
262
  else:
251
263
  # otherwise default location will be the data root level
252
264
  _config["output"]["location"] = os.sep.join(
253
- self.scan.path, "saaxis_results"
265
+ [
266
+ self.scan.path,
267
+ "saaxis_results",
268
+ ]
254
269
  )
255
270
  if "reconstruction" not in _config:
256
271
  _config["reconstruction"] = {}