tomwer 1.2.1__py3-none-any.whl → 1.3.12__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 (334) hide show
  1. orangecontrib/tomwer/tutorials/icat_publication.ows +58 -0
  2. orangecontrib/tomwer/widgets/__init__.py +11 -11
  3. orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +2 -2
  4. orangecontrib/tomwer/widgets/control/DataListOW.py +9 -7
  5. orangecontrib/tomwer/widgets/control/DataListenerOW.py +6 -6
  6. orangecontrib/tomwer/widgets/control/DataSelectorOW.py +21 -10
  7. orangecontrib/tomwer/widgets/control/DataValidatorOW.py +6 -6
  8. orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +24 -7
  9. orangecontrib/tomwer/widgets/control/EmailOW.py +4 -4
  10. orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +3 -3
  11. orangecontrib/tomwer/widgets/control/NXTomomillOW.py +64 -23
  12. orangecontrib/tomwer/widgets/control/NXtomoConcatenate.py +20 -8
  13. orangecontrib/tomwer/widgets/control/NotifierOW.py +1 -0
  14. orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +6 -6
  15. orangecontrib/tomwer/widgets/control/VolumeSelector.py +7 -4
  16. orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +182 -182
  17. orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +5 -5
  18. orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +4 -4
  19. orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +3 -3
  20. orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +8 -1
  21. orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +3 -3
  22. orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +3 -3
  23. orangecontrib/tomwer/widgets/icat/PublishProcessedDataOW.py +115 -0
  24. orangecontrib/tomwer/widgets/icat/RawDataScreenshotCreatorOW.py +98 -0
  25. orangecontrib/tomwer/widgets/icat/SaveToGalleryAndPublishOW.py +129 -0
  26. orangecontrib/tomwer/widgets/icat/__init__.py +13 -0
  27. orangecontrib/tomwer/widgets/icat/icons/add_gallery.png +0 -0
  28. orangecontrib/tomwer/widgets/icat/icons/add_gallery.svg +82 -0
  29. orangecontrib/tomwer/widgets/icat/icons/publish_processed_data.png +0 -0
  30. orangecontrib/tomwer/widgets/icat/icons/publish_processed_data.svg +95 -0
  31. orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.png +0 -0
  32. orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.svg +143 -0
  33. orangecontrib/tomwer/widgets/icons/tomwer_data_portal.png +0 -0
  34. orangecontrib/tomwer/widgets/icons/tomwer_data_portal.svg +76 -0
  35. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +22 -20
  36. orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +19 -3
  37. orangecontrib/tomwer/widgets/reconstruction/NabuHelicalPrepareWeightsDoubleOW.py +184 -169
  38. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +23 -0
  39. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +39 -5
  40. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +18 -22
  41. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +18 -26
  42. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +15 -19
  43. orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +9 -9
  44. orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
  45. orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +1 -1
  46. orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +3 -3
  47. orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -1
  48. orangecontrib/tomwer/widgets/visualization/VolumeViewerOW.py +3 -29
  49. tomwer/__main__.py +7 -64
  50. tomwer/app/axis.py +3 -3
  51. tomwer/app/canvas.py +8 -0
  52. tomwer/app/canvas_launcher/config.py +16 -14
  53. tomwer/app/canvas_launcher/environ.py +1 -0
  54. tomwer/app/canvas_launcher/mainwindow.py +4 -1
  55. tomwer/app/darkref.py +1 -1
  56. tomwer/app/darkrefpatch.py +1 -1
  57. tomwer/app/diffframe.py +3 -3
  58. tomwer/app/imagekeyeditor.py +5 -5
  59. tomwer/app/imagekeyupgrader.py +5 -5
  60. tomwer/app/intensitynormalization.py +14 -13
  61. tomwer/app/{saaxis.py → multicor.py} +3 -3
  62. tomwer/app/{sadeltabeta.py → multipag.py} +3 -3
  63. tomwer/app/nabuapp.py +0 -11
  64. tomwer/app/radiostack.py +6 -4
  65. tomwer/app/samplemoved.py +3 -2
  66. tomwer/app/scanviewer.py +4 -2
  67. tomwer/app/sinogramviewer.py +3 -2
  68. tomwer/app/slicestack.py +3 -2
  69. tomwer/app/zstitching.py +88 -6
  70. tomwer/core/cluster/cluster.py +26 -0
  71. tomwer/core/log/logger.py +7 -5
  72. tomwer/core/process/conditions/filters.py +1 -1
  73. tomwer/core/process/control/datalistener/datalistener.py +19 -14
  74. tomwer/core/process/control/datawatcher/edfdwprocess.py +0 -9
  75. tomwer/core/process/control/nxtomoconcatenate.py +13 -13
  76. tomwer/core/process/control/nxtomomill.py +92 -34
  77. tomwer/core/process/control/scantransfer.py +20 -43
  78. tomwer/core/process/control/scanvalidator.py +3 -2
  79. tomwer/core/process/control/test/test_concatenate_nxtomos.py +9 -9
  80. tomwer/core/process/control/test/test_email.py +4 -4
  81. tomwer/core/process/control/test/test_h52nx_process.py +59 -7
  82. tomwer/core/process/control/test/test_volume_link.py +64 -64
  83. tomwer/core/process/control/timer.py +1 -1
  84. tomwer/core/process/control/volumesymlink.py +200 -200
  85. tomwer/core/process/edit/darkflatpatch.py +14 -15
  86. tomwer/core/process/edit/imagekeyeditor.py +41 -39
  87. tomwer/core/process/icat/__init__.py +0 -0
  88. tomwer/core/process/icat/createscreenshots.py +100 -0
  89. tomwer/core/process/icat/gallery.py +377 -0
  90. tomwer/core/process/icat/icatbase.py +36 -0
  91. tomwer/core/process/icat/publish.py +228 -0
  92. tomwer/core/process/icat/screenshots.py +27 -0
  93. tomwer/core/process/output.py +52 -0
  94. tomwer/core/process/reconstruction/axis/axis.py +280 -69
  95. tomwer/core/process/reconstruction/axis/mode.py +163 -48
  96. tomwer/core/process/reconstruction/axis/params.py +29 -21
  97. tomwer/core/process/reconstruction/darkref/darkrefs.py +41 -127
  98. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +4 -3
  99. tomwer/core/process/reconstruction/darkref/params.py +1 -1
  100. tomwer/core/process/reconstruction/nabu/castvolume.py +4 -4
  101. tomwer/core/process/reconstruction/nabu/helical.py +9 -5
  102. tomwer/core/process/reconstruction/nabu/nabucommon.py +71 -78
  103. tomwer/core/process/reconstruction/nabu/nabuscores.py +425 -53
  104. tomwer/core/process/reconstruction/nabu/nabuslices.py +114 -93
  105. tomwer/core/process/reconstruction/nabu/nabuvolume.py +54 -27
  106. tomwer/core/process/reconstruction/nabu/plane.py +9 -0
  107. tomwer/core/process/reconstruction/nabu/settings.py +2 -2
  108. tomwer/core/process/reconstruction/nabu/utils.py +164 -26
  109. tomwer/core/process/reconstruction/output.py +108 -0
  110. tomwer/core/process/reconstruction/saaxis/saaxis.py +238 -264
  111. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +151 -87
  112. tomwer/core/process/reconstruction/scores/params.py +7 -4
  113. tomwer/core/process/reconstruction/scores/scores.py +13 -0
  114. tomwer/core/process/reconstruction/test/test_axis_params.py +2 -2
  115. tomwer/core/process/reconstruction/test/test_darkref.py +3 -3
  116. tomwer/core/process/reconstruction/test/test_darkref_copy.py +7 -7
  117. tomwer/core/process/reconstruction/test/test_saaxis.py +3 -4
  118. tomwer/core/process/reconstruction/test/test_sadeltabeta.py +2 -2
  119. tomwer/core/process/stitching/nabustitcher.py +13 -12
  120. tomwer/core/process/task.py +34 -26
  121. tomwer/core/process/test/test_axis.py +13 -12
  122. tomwer/core/process/test/test_dark_and_flat.py +10 -7
  123. tomwer/core/process/test/test_data_transfer.py +10 -8
  124. tomwer/core/process/test/test_nabu.py +14 -6
  125. tomwer/core/process/test/test_normalization.py +4 -4
  126. tomwer/core/scan/blissscan.py +3 -3
  127. tomwer/core/scan/edfscan.py +13 -10
  128. tomwer/core/scan/hdf5scan.py +19 -530
  129. tomwer/core/scan/nxtomoscan.py +534 -0
  130. tomwer/core/scan/scanbase.py +72 -44
  131. tomwer/core/scan/scanfactory.py +13 -13
  132. tomwer/core/scan/test/test_edf.py +2 -2
  133. tomwer/core/scan/test/test_future_scan.py +3 -3
  134. tomwer/core/scan/test/test_h5.py +18 -16
  135. tomwer/core/scan/test/test_process_registration.py +4 -40
  136. tomwer/core/scan/test/test_scan.py +5 -78
  137. tomwer/core/settings.py +22 -2
  138. tomwer/core/test/test_scanutils.py +8 -7
  139. tomwer/core/test/test_utils.py +35 -28
  140. tomwer/core/tomwer_object.py +1 -1
  141. tomwer/core/utils/__init__.py +0 -466
  142. tomwer/core/utils/deprecation.py +1 -1
  143. tomwer/core/utils/dictutils.py +14 -0
  144. tomwer/core/utils/lbsram.py +35 -0
  145. tomwer/core/utils/nxtomoutils.py +1 -1
  146. tomwer/core/utils/scanutils.py +6 -6
  147. tomwer/core/utils/spec.py +263 -0
  148. tomwer/core/volume/edfvolume.py +6 -6
  149. tomwer/core/volume/hdf5volume.py +6 -6
  150. tomwer/core/volume/jp2kvolume.py +6 -6
  151. tomwer/core/volume/rawvolume.py +6 -6
  152. tomwer/core/volume/tiffvolume.py +12 -12
  153. tomwer/core/volume/volumefactory.py +2 -2
  154. tomwer/gui/cluster/slurm.py +274 -65
  155. tomwer/gui/cluster/supervisor.py +12 -0
  156. tomwer/gui/cluster/test/test_cluster.py +14 -2
  157. tomwer/gui/cluster/test/test_supervisor.py +3 -3
  158. tomwer/gui/configuration/__init__.py +0 -0
  159. tomwer/gui/{reconstruction/nabu → configuration}/action.py +1 -32
  160. tomwer/gui/configuration/level.py +22 -0
  161. tomwer/gui/control/actions.py +54 -0
  162. tomwer/gui/control/datalist.py +83 -16
  163. tomwer/gui/control/datalistener.py +4 -16
  164. tomwer/gui/control/datawatcher/controlwidget.py +2 -4
  165. tomwer/gui/control/datawatcher/datawatcher.py +1 -24
  166. tomwer/gui/control/{email.py → emailnotifier.py} +9 -18
  167. tomwer/gui/control/history.py +2 -2
  168. tomwer/gui/control/observations.py +2 -2
  169. tomwer/gui/control/reducedarkflatselector.py +9 -9
  170. tomwer/gui/control/selectorwidgetbase.py +36 -9
  171. tomwer/gui/control/serie/seriecreator.py +5 -22
  172. tomwer/gui/control/test/test_email.py +1 -1
  173. tomwer/gui/control/test/test_scanvalidator.py +6 -5
  174. tomwer/gui/control/test/test_single_tomo_obj.py +3 -3
  175. tomwer/gui/control/tomoobjdisplaymode.py +8 -0
  176. tomwer/gui/debugtools/datasetgenerator.py +3 -3
  177. tomwer/gui/edit/dkrfpatch.py +20 -26
  178. tomwer/gui/edit/imagekeyeditor.py +11 -12
  179. tomwer/gui/edit/nxtomoeditor.py +111 -44
  180. tomwer/gui/edit/nxtomowarmer.py +7 -6
  181. tomwer/gui/edit/test/test_dkrf_patch.py +13 -13
  182. tomwer/gui/edit/test/test_image_key_editor.py +3 -3
  183. tomwer/gui/edit/test/test_nx_editor.py +40 -16
  184. tomwer/gui/icat/__init__.py +0 -0
  185. tomwer/gui/icat/createscreenshots.py +80 -0
  186. tomwer/gui/icat/gallery.py +214 -0
  187. tomwer/gui/icat/publish.py +187 -0
  188. tomwer/gui/imagefromfile.py +2 -2
  189. tomwer/gui/qfolderdialog.py +24 -1
  190. tomwer/gui/reconstruction/axis/CompareImages.py +88 -168
  191. tomwer/gui/reconstruction/axis/axis.py +171 -57
  192. tomwer/gui/reconstruction/axis/radioaxis.py +122 -257
  193. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +3 -2
  194. tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -1
  195. tomwer/gui/reconstruction/nabu/castvolume.py +14 -3
  196. tomwer/gui/reconstruction/nabu/check.py +9 -9
  197. tomwer/gui/reconstruction/nabu/helical.py +29 -12
  198. tomwer/gui/reconstruction/nabu/nabuconfig/base.py +2 -4
  199. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +2 -1
  200. tomwer/gui/reconstruction/nabu/nabuconfig/output.py +126 -35
  201. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +39 -32
  202. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +222 -31
  203. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +57 -27
  204. tomwer/gui/reconstruction/nabu/nabuflow.py +12 -20
  205. tomwer/gui/reconstruction/nabu/slices.py +10 -11
  206. tomwer/gui/reconstruction/nabu/volume.py +22 -10
  207. tomwer/gui/reconstruction/normalization/intensity.py +18 -48
  208. tomwer/gui/reconstruction/saaxis/corrangeselector.py +8 -24
  209. tomwer/gui/reconstruction/saaxis/dimensionwidget.py +1 -1
  210. tomwer/gui/reconstruction/saaxis/saaxis.py +9 -21
  211. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +45 -12
  212. tomwer/gui/reconstruction/scores/control.py +2 -9
  213. tomwer/gui/reconstruction/scores/scoreplot.py +13 -11
  214. tomwer/gui/reconstruction/test/test_axis.py +41 -16
  215. tomwer/gui/reconstruction/test/test_nabu.py +31 -9
  216. tomwer/gui/reconstruction/test/test_saaxis.py +3 -3
  217. tomwer/gui/reconstruction/test/test_sadeltabeta.py +12 -2
  218. tomwer/gui/settings.py +5 -28
  219. tomwer/gui/stackplot.py +2 -5
  220. tomwer/gui/stitching/action.py +49 -0
  221. tomwer/gui/stitching/config/axisparams.py +7 -24
  222. tomwer/gui/stitching/config/output.py +10 -8
  223. tomwer/gui/stitching/config/positionoveraxis.py +22 -23
  224. tomwer/gui/stitching/normalization.py +117 -0
  225. tomwer/gui/stitching/stitchandbackground.py +4 -6
  226. tomwer/gui/stitching/stitching.py +267 -45
  227. tomwer/gui/stitching/stitching_preview.py +62 -55
  228. tomwer/gui/stitching/stitching_raw.py +13 -12
  229. tomwer/gui/stitching/z_stitching/fineestimation.py +0 -60
  230. tomwer/gui/utils/buttons.py +112 -29
  231. tomwer/gui/utils/inputwidget.py +43 -25
  232. tomwer/gui/utils/lineselector/lineselector.py +1 -1
  233. tomwer/gui/utils/scandescription.py +4 -0
  234. tomwer/gui/utils/step.py +144 -0
  235. tomwer/gui/utils/unitsystem.py +2 -5
  236. tomwer/gui/utils/vignettes.py +176 -15
  237. tomwer/gui/visualization/dataviewer.py +48 -35
  238. tomwer/gui/visualization/diffviewer/diffviewer.py +7 -16
  239. tomwer/gui/visualization/diffviewer/shiftwidget.py +2 -5
  240. tomwer/gui/visualization/scanoverview.py +1 -1
  241. tomwer/gui/visualization/sinogramviewer.py +20 -36
  242. tomwer/gui/visualization/test/test_diffviewer.py +3 -3
  243. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +4 -4
  244. tomwer/gui/visualization/test/test_sinogramviewer.py +2 -2
  245. tomwer/gui/visualization/test/test_stacks.py +3 -3
  246. tomwer/gui/visualization/test/test_volumeviewer.py +65 -67
  247. tomwer/gui/visualization/volumeviewer.py +114 -113
  248. tomwer/io/utils/h5pyutils.py +3 -3
  249. tomwer/io/utils/raw_and_processed_data.py +84 -0
  250. tomwer/io/utils/tomoobj.py +4 -6
  251. tomwer/io/utils/utils.py +7 -7
  252. tomwer/resources/gui/icons/parameters.svg +1 -1
  253. tomwer/resources/gui/icons/ruler.png +0 -0
  254. tomwer/resources/gui/icons/ruler.svg +273 -0
  255. tomwer/resources/gui/icons/short_description.png +0 -0
  256. tomwer/resources/gui/icons/short_description.svg +58 -0
  257. tomwer/resources/gui/icons/url.png +0 -0
  258. tomwer/resources/gui/icons/url.svg +58 -0
  259. tomwer/resources/gui/illustrations/no_rot.svg +1 -1
  260. tomwer/synctools/stacks/edit/darkflatpatch.py +19 -14
  261. tomwer/synctools/stacks/edit/imagekeyeditor.py +2 -2
  262. tomwer/synctools/stacks/reconstruction/axis.py +4 -4
  263. tomwer/synctools/stacks/reconstruction/castvolume.py +22 -7
  264. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +25 -20
  265. tomwer/synctools/stacks/reconstruction/nabu.py +2 -2
  266. tomwer/synctools/stacks/reconstruction/normalization.py +2 -2
  267. tomwer/synctools/stacks/reconstruction/saaxis.py +2 -2
  268. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +2 -2
  269. tomwer/synctools/test/test_darkRefs.py +7 -58
  270. tomwer/synctools/test/test_foldertransfer.py +6 -6
  271. tomwer/synctools/utils/scanstages.py +6 -6
  272. tomwer/tests/conftest.py +34 -0
  273. tomwer/tests/datasets.py +13 -0
  274. tomwer/tests/test_scripts.py +91 -41
  275. tomwer/tests/utils.py +5 -0
  276. tomwer/third_part/WaitingOverlay.py +110 -0
  277. tomwer/third_part/__init__.py +0 -0
  278. tomwer/version.py +2 -2
  279. tomwer-1.3.12-py3.11-nspkg.pth +1 -0
  280. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/METADATA +73 -58
  281. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/RECORD +287 -286
  282. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/WHEEL +1 -1
  283. orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +0 -197
  284. orangecontrib/tomwer/widgets/reconstruction/icons/XY_lamino.svg +0 -168
  285. orangecontrib/tomwer/widgets/reconstruction/icons/XZ_lamino.svg +0 -275
  286. orangecontrib/tomwer/widgets/reconstruction/icons/YZ_lamino.svg +0 -182
  287. tomwer/app/lamino.py +0 -143
  288. tomwer/core/process/reconstruction/lamino/__init__.py +0 -1
  289. tomwer/core/process/reconstruction/lamino/tofu.py +0 -1000
  290. tomwer/core/process/test/test_lamino.py +0 -76
  291. tomwer/core/test/test_lamino.py +0 -92
  292. tomwer/gui/reconstruction/lamino/__init__.py +0 -31
  293. tomwer/gui/reconstruction/lamino/tofu/TofuOptionLoader.py +0 -107
  294. tomwer/gui/reconstruction/lamino/tofu/__init__.py +0 -1
  295. tomwer/gui/reconstruction/lamino/tofu/misc.py +0 -148
  296. tomwer/gui/reconstruction/lamino/tofu/projections.py +0 -896
  297. tomwer/gui/reconstruction/lamino/tofu/settings.py +0 -75
  298. tomwer/gui/reconstruction/lamino/tofu/tofu.py +0 -432
  299. tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +0 -567
  300. tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +0 -760
  301. tomwer/gui/reconstruction/test/test_lamino.py +0 -189
  302. tomwer/resources/gui/icons/esrf_1.svg +0 -307
  303. tomwer/resources/gui/icons/lamino_parameters.svg +0 -70
  304. tomwer/resources/gui/icons/triangle.svg +0 -80
  305. tomwer/resources/gui/illustrations/lamino_angle.png +0 -0
  306. tomwer/resources/gui/illustrations/lamino_angle.svg +0 -509
  307. tomwer/resources/gui/illustrations/lamino_beta_angle.png +0 -0
  308. tomwer/resources/gui/illustrations/lamino_beta_angle.svg +0 -97
  309. tomwer/resources/gui/illustrations/lamino_theta_angle.png +0 -0
  310. tomwer/resources/gui/illustrations/lamino_theta_angle.svg +0 -368
  311. tomwer/resources/gui/illustrations/manual_slice.png +0 -0
  312. tomwer/resources/gui/illustrations/manual_slice.svg +0 -221
  313. tomwer/resources/gui/illustrations/psi_angle.png +0 -0
  314. tomwer/resources/gui/illustrations/psi_angle.svg +0 -479
  315. tomwer/resources/gui/illustrations/rotation_center.png +0 -0
  316. tomwer/resources/gui/illustrations/rotation_center.svg +0 -276
  317. tomwer/resources/gui/illustrations/slice_stack.png +0 -0
  318. tomwer/resources/gui/illustrations/slice_stack.svg +0 -266
  319. tomwer/resources/gui/illustrations/xy_slice.png +0 -0
  320. tomwer/resources/gui/illustrations/xy_slice.svg +0 -269
  321. tomwer/resources/gui/illustrations/xz_slice.png +0 -0
  322. tomwer/resources/gui/illustrations/xz_slice.svg +0 -270
  323. tomwer/resources/gui/illustrations/yz_slice.png +0 -0
  324. tomwer/resources/gui/illustrations/yz_slice.svg +0 -270
  325. tomwer/synctools/stacks/reconstruction/lamino.py +0 -233
  326. tomwer/synctools/test/test_scanstages.py +0 -162
  327. tomwer/tests/utils/__init__.py +0 -247
  328. tomwer/tests/utils/utilstest.py +0 -220
  329. tomwer-1.2.1-py3.11-nspkg.pth +0 -1
  330. /tomwer/core/process/control/{email.py → emailnotifier.py} +0 -0
  331. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/LICENSE +0 -0
  332. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/entry_points.txt +0 -0
  333. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/namespace_packages.txt +0 -0
  334. {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/top_level.txt +0 -0
@@ -35,12 +35,20 @@ import os
35
35
  import gc
36
36
  from tomwer.io.utils import format_stderr_stdout
37
37
  from silx.utils.deprecation import deprecated, deprecated_warning
38
+ from silx.io.utils import open as open_hdf5
38
39
 
39
40
  from processview.core.manager.manager import ProcessManager, DatasetState
40
41
 
41
42
  from tomwer.core.futureobject import FutureTomwerObject
42
43
  from tomwer.core.utils.scanutils import data_identifier_to_scan
43
44
  from tomwer.core.utils.slurm import is_slurm_available
45
+ from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
46
+ from tomwer.core.process.reconstruction.nabu.utils import slice_index_to_int
47
+ from tomwer.core.process.icat.gallery import (
48
+ IcatScreenshots,
49
+ deduce_dataset_gallery_location,
50
+ )
51
+ from tomwer.core.volume.volumefactory import VolumeFactory
44
52
 
45
53
  try:
46
54
  from nabu.pipeline.fullfield.reconstruction import ( # noqa F401
@@ -77,11 +85,10 @@ from processview.core.superviseprocess import SuperviseProcess
77
85
  from silx.io.dictdump import h5todict
78
86
  from silx.io.utils import h5py_read_dataset
79
87
  from silx.utils.enum import Enum as _Enum
80
- from tomoscan.io import HDF5File
81
88
 
82
89
  from tomwer.core.process.task import Task
83
90
  from tomwer.core.scan.edfscan import EDFTomoScan
84
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
91
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
85
92
  from tomwer.core.scan.scanbase import TomwerScanBase
86
93
  from tomwer.core.scan.scanfactory import ScanFactory
87
94
  from tomwer.io.utils.h5pyutils import EntryReader
@@ -166,14 +173,6 @@ def run_slices_reconstruction(
166
173
 
167
174
  # handle special cases like several db...
168
175
  nabu_configurations = interpret_tomwer_configuration(config, scan=scan)
169
- if "phase" in config and "delta_beta" in config["phase"]:
170
- db_list = utils.retrieve_lst_of_value_from_str(
171
- config["phase"]["delta_beta"], type_=float
172
- )
173
- else:
174
- db_list = ()
175
- ask_sinogram_registration = len(db_list) > 0
176
- ask_sinogram_load = False
177
176
  output_urls = []
178
177
  stderrs = []
179
178
  stdouts = []
@@ -192,9 +191,8 @@ def run_slices_reconstruction(
192
191
  scan=scan,
193
192
  slice_index=slice_index,
194
193
  dry_run=dry_run,
195
- ask_sinogram_registration=ask_sinogram_registration,
196
- ask_sinogram_load=ask_sinogram_load,
197
194
  instanciate_class_only=instanciate_classes_only,
195
+ axis=config.get("reconstruction", {}).get("slice_plane", "XY"),
198
196
  )
199
197
 
200
198
  # specific treatments of results
@@ -210,7 +208,7 @@ def run_slices_reconstruction(
210
208
  assert not is_cluster_job, "cluster job should not return ResultsLocalRun"
211
209
  stderrs.append(result.std_err)
212
210
  stdouts.append(result.std_out)
213
- output_urls.extend(result.results_urls)
211
+ output_urls.extend(result.results_identifiers)
214
212
  # if slice_index is None this mean that we are simply creating the
215
213
  # .cfg file for nabu full volume.
216
214
  elif isinstance(result, ResultSlurmRun):
@@ -230,9 +228,6 @@ def run_slices_reconstruction(
230
228
  final_configs.append(result.config)
231
229
  all_succeed = all_succeed and result.success
232
230
 
233
- if ask_sinogram_registration:
234
- ask_sinogram_load = True
235
- ask_sinogram_registration = False
236
231
  if advancement is not None:
237
232
  advancement.increaseAdvancement(1)
238
233
 
@@ -263,11 +258,7 @@ class NabuSlicesTask(
263
258
  "dry_run",
264
259
  "serialize_output_data",
265
260
  ),
266
- output_names=(
267
- "data",
268
- "nabu_params",
269
- "future_tomo_obj",
270
- ),
261
+ output_names=("data", "nabu_params", "future_tomo_obj", "screenshots"),
271
262
  ):
272
263
  """
273
264
  Definition of the nabu reconstruction volume reconstruction process
@@ -313,7 +304,7 @@ class NabuSlicesTask(
313
304
  assert isinstance(configuration, dict), "configuration is expected to be a dict"
314
305
 
315
306
  entry = "entry"
316
- if isinstance(scan, HDF5TomoScan):
307
+ if isinstance(scan, NXtomoScan):
317
308
  entry = scan.entry
318
309
 
319
310
  output_urls = []
@@ -358,7 +349,7 @@ class NabuSlicesTask(
358
349
  ), "cluster job should not return ResultsLocalRun"
359
350
  stderrs.append(result.std_err)
360
351
  stdouts.append(result.std_out)
361
- output_urls.extend(result.results_urls)
352
+ output_urls.extend(result.results_identifiers)
362
353
  # if slice_index is None this mean that we are simply creating the
363
354
  # .cfg file for nabu full volume.
364
355
  elif isinstance(result, ResultSlurmRun):
@@ -392,6 +383,21 @@ class NabuSlicesTask(
392
383
  scan.set_latest_reconstructions(output_urls)
393
384
  future_tomo_obj = None
394
385
 
386
+ volume_urls = []
387
+ for rec_identifier in scan.latest_reconstructions:
388
+ volume_urls.extend(
389
+ VolumeFactory.from_identifier_to_vol_urls(rec_identifier)
390
+ )
391
+
392
+ self.outputs.screenshots = IcatScreenshots(
393
+ data_dir=deduce_dataset_gallery_location(scan),
394
+ screenshots={
395
+ os.path.splitext(os.path.basename(url.file_path()))[0]: url
396
+ for url in volume_urls
397
+ },
398
+ scan=scan,
399
+ )
400
+
395
401
  process_index = scan.pop_process_index()
396
402
  # update processes information / registration
397
403
  gc.collect()
@@ -426,15 +432,14 @@ class NabuSlicesTask(
426
432
  )
427
433
 
428
434
  # register result
429
- with scan.acquire_process_file_lock():
430
- self.register_process(
431
- process_file=scan.process_file,
432
- entry=entry,
433
- configuration=configuration,
434
- results={},
435
- process_index=process_index,
436
- overwrite=True,
437
- )
435
+ self.register_process(
436
+ process_file=scan.process_file,
437
+ entry=entry,
438
+ configuration=configuration,
439
+ results={},
440
+ process_index=process_index,
441
+ overwrite=True,
442
+ )
438
443
  if self.get_input_value("serialize_output_data", True):
439
444
  self.outputs.data = scan.to_dict()
440
445
  else:
@@ -476,7 +481,7 @@ class NabuSlicesTask(
476
481
  :rtype:dict
477
482
  """
478
483
  if entry is None:
479
- with HDF5File(process_file, "r", swmr=True) as h5f:
484
+ with open_hdf5(process_file) as h5f:
480
485
  entries = NabuSlicesTask._get_process_nodes(
481
486
  root_node=h5f, process=NabuSlicesTask
482
487
  )
@@ -492,7 +497,7 @@ class NabuSlicesTask(
492
497
  configuration_path = None
493
498
  res = {}
494
499
 
495
- with HDF5File(process_file, "r", swmr=True) as h5f:
500
+ with open_hdf5(process_file) as h5f:
496
501
  nabu_nodes = NabuSlicesTask._get_process_nodes(
497
502
  root_node=h5f[entry], process=NabuSlicesTask
498
503
  )
@@ -570,7 +575,13 @@ def interpret_tomwer_configuration(
570
575
  return nabu_config
571
576
 
572
577
  if "tomwer_slices" in config and scan is not None:
573
- slices = list(NabuSliceMode.getSlices(config["tomwer_slices"], scan))
578
+ slices = list(
579
+ NabuSliceMode.getSlices(
580
+ config["tomwer_slices"],
581
+ scan=scan,
582
+ axis=config.get("reconstruction", {}).get("slice_plane", "XY"),
583
+ )
584
+ )
574
585
  else:
575
586
  slices = []
576
587
 
@@ -614,9 +625,8 @@ class SingleSliceRunner(_NabuBaseReconstructor):
614
625
  config: dict,
615
626
  dry_run: bool,
616
627
  slice_index: Union[int, str, None],
628
+ axis: NabuPlane,
617
629
  target: Target,
618
- ask_sinogram_registration: bool,
619
- ask_sinogram_load: bool,
620
630
  cluster_config: Optional[dict],
621
631
  process_name: str,
622
632
  add_to_latest_reconstructions: bool = True,
@@ -627,13 +637,12 @@ class SingleSliceRunner(_NabuBaseReconstructor):
627
637
  target=target,
628
638
  cluster_config=cluster_config,
629
639
  process_name=process_name,
640
+ axis=axis,
630
641
  )
631
642
  self._slice_index = slice_index
632
643
  if not isinstance(config, dict):
633
644
  raise TypeError(f"config is expected to be a dictionary not {type(dict)}")
634
645
  self._config = config
635
- self._ask_sinogram_registration = ask_sinogram_registration
636
- self._ask_sinogram_load = ask_sinogram_load
637
646
  self._add_to_latest_reconstructions = add_to_latest_reconstructions
638
647
 
639
648
  @property
@@ -644,14 +653,6 @@ class SingleSliceRunner(_NabuBaseReconstructor):
644
653
  def config(self):
645
654
  return self._config
646
655
 
647
- @property
648
- def ask_sinogram_load(self):
649
- return self._ask_sinogram_load
650
-
651
- @property
652
- def ask_sinogram_registration(self):
653
- return self._ask_sinogram_registration
654
-
655
656
  @property
656
657
  def add_to_latest_reconstructions(self):
657
658
  return self._add_to_latest_reconstructions
@@ -668,12 +669,11 @@ class SingleSliceRunner(_NabuBaseReconstructor):
668
669
  :raise: TIMEOUT_SLURM_JOB_SUBMISSION if not all workers spwan
669
670
  """
670
671
  if isinstance(self.slice_index, str):
671
- if self.slice_index == "middle":
672
- self._slice_index = self.scan.dim_2 // 2
673
- else:
674
- raise ValueError(
675
- f"slice index is expected to an int or 'middle' and not {type(self.slice_index)}"
676
- )
672
+ self._slice_index = slice_index_to_int(
673
+ slice_index=self.slice_index,
674
+ scan=self.scan,
675
+ axis=self.axis,
676
+ )
677
677
  elif (
678
678
  isinstance(self.slice_index, float)
679
679
  and int(self.slice_index) == self.slice_index
@@ -696,32 +696,26 @@ class SingleSliceRunner(_NabuBaseReconstructor):
696
696
  # force overwrite results
697
697
  if "output" not in config:
698
698
  config["output"] = {}
699
- # handle nabu sinogram step
700
- if self.scan.process_file is not None:
701
- steps_file_basename, _ = os.path.splitext(self.scan.process_file)
702
- steps_file_basename = "_".join(
703
- ("steps_file_basename", "nabu", "sinogram", "save", "step")
704
- )
705
- steps_file_basename = steps_file_basename + ".hdf5"
706
- steps_file = os.path.join(
707
- os.path.dirname(self.scan.process_file), steps_file_basename
708
- )
709
- else:
710
- steps_file = ""
711
699
 
712
700
  config["output"].update({"overwrite_results": 1})
713
- config["pipeline"] = {
714
- "save_steps": "sinogram" if self.ask_sinogram_registration else "",
715
- "resume_from_step": "sinogram" if self.ask_sinogram_load else "",
716
- "steps_file": steps_file,
717
- }
718
701
 
719
702
  config, cfg_folder = self._treateOutputSliceConfig(config)
720
703
  # the policy is to save nabu .cfg file at the same location as the
721
704
  # force overwrite results
722
705
  if self.slice_index is not None:
723
- config["reconstruction"]["start_z"] = self.slice_index
724
- config["reconstruction"]["end_z"] = self.slice_index
706
+ if self.axis is NabuPlane.YZ:
707
+ config["reconstruction"]["start_x"] = self.slice_index
708
+ config["reconstruction"]["end_x"] = self.slice_index
709
+ elif self.axis is NabuPlane.XZ:
710
+ config["reconstruction"]["start_y"] = self.slice_index
711
+ config["reconstruction"]["end_y"] = self.slice_index
712
+ elif self.axis is NabuPlane.XY:
713
+ config["reconstruction"]["start_z"] = self.slice_index
714
+ config["reconstruction"]["end_z"] = self.slice_index
715
+ else:
716
+ raise ValueError(
717
+ f"self.axis has an invalid value: {self.axis} when expected to be in {NabuPlane.values()}"
718
+ )
725
719
 
726
720
  if self.slice_index is not None:
727
721
  os.makedirs(config["output"]["location"], exist_ok=True)
@@ -749,8 +743,6 @@ class SingleSliceRunner(_NabuBaseReconstructor):
749
743
  self._process_config(
750
744
  config_to_dump=config_to_dump,
751
745
  config_file=conf_file,
752
- start_z=None,
753
- end_z=None,
754
746
  info="nabu slice reconstruction",
755
747
  file_format=config_to_dump["output"]["file_format"],
756
748
  process_name=self.process_name,
@@ -784,9 +776,7 @@ class SingleSliceRunner(_NabuBaseReconstructor):
784
776
  file_format=file_format,
785
777
  scan=self.scan,
786
778
  slice_index=None,
787
- start_z=None,
788
- end_z=None,
789
- expects_single_slice=True,
779
+ axis=self.axis,
790
780
  )
791
781
 
792
782
  return (CallBack(callback, self.scan),)
@@ -795,18 +785,25 @@ class SingleSliceRunner(_NabuBaseReconstructor):
795
785
 
796
786
  @staticmethod
797
787
  def get_file_basename_reconstruction(
798
- scan, pag, ctf, db, slice_index: Union[str, int]
788
+ scan,
789
+ pag,
790
+ ctf,
791
+ db,
792
+ slice_index: Union[str, int],
793
+ axis: NabuPlane,
799
794
  ):
795
+ axis = NabuPlane.from_value(axis)
800
796
  if pag:
801
797
  assert db is not None, "if paganin defined, db should not be None"
802
- if slice_index == "middle":
803
- slice_index = scan.dim_2 // 2
798
+ if slice_index is not None:
799
+ slice_index = slice_index_to_int(slice_index, scan=scan, axis=axis)
800
+
804
801
  assert type(db) in (int, type(None))
805
- if isinstance(scan, HDF5TomoScan):
802
+ if isinstance(scan, NXtomoScan):
806
803
  basename, _ = os.path.splitext(scan.master_file)
807
804
  basename = os.path.basename(basename)
808
805
  try:
809
- with HDF5File(scan.master_file, mode="r") as h5f:
806
+ with open_hdf5(scan.master_file) as h5f:
810
807
  if len(h5f.keys()) > 1:
811
808
  # if there is more than one entry in the file append the entry name to the file basename
812
809
  basename = "_".join((basename, scan.entry.lstrip("/")))
@@ -828,6 +825,8 @@ class SingleSliceRunner(_NabuBaseReconstructor):
828
825
  basename + "slice_pag",
829
826
  str(slice_index).zfill(6),
830
827
  "db" + str(db).zfill(4),
828
+ "plane",
829
+ axis.value,
831
830
  )
832
831
  )
833
832
  elif ctf:
@@ -836,13 +835,22 @@ class SingleSliceRunner(_NabuBaseReconstructor):
836
835
  basename + "slice_ctf",
837
836
  str(slice_index).zfill(6),
838
837
  "db" + str(db).zfill(4),
838
+ "plane",
839
+ axis.value,
839
840
  )
840
841
  )
841
842
  else:
842
- return "_".join((basename + "slice", str(slice_index).zfill(6)))
843
+ return "_".join(
844
+ (
845
+ basename + "slice",
846
+ str(slice_index).zfill(6),
847
+ "plane",
848
+ axis.value,
849
+ )
850
+ )
843
851
 
844
852
  @docstring(_NabuBaseReconstructor)
845
- def _get_file_basename_reconstruction(self, pag, db, ctf):
853
+ def _get_file_basename_reconstruction(self, pag, db, ctf, axis):
846
854
  """
847
855
 
848
856
  :param TomwerScanBase scan: scan reconstructed
@@ -854,7 +862,12 @@ class SingleSliceRunner(_NabuBaseReconstructor):
854
862
  :return: basename of the file reconstructed (without any extension)
855
863
  """
856
864
  return self.get_file_basename_reconstruction(
857
- scan=self.scan, db=db, pag=pag, slice_index=self.slice_index, ctf=ctf
865
+ scan=self.scan,
866
+ db=db,
867
+ pag=pag,
868
+ slice_index=self.slice_index,
869
+ ctf=ctf,
870
+ axis=axis,
858
871
  )
859
872
 
860
873
 
@@ -863,12 +876,11 @@ def run_single_slice_reconstruction(
863
876
  nabu_config,
864
877
  dry_run,
865
878
  slice_index: Union[int, str, None],
866
- ask_sinogram_registration: bool,
867
- ask_sinogram_load: bool,
868
879
  process_id: Optional[int] = None,
869
880
  cluster_config: Optional[dict] = None,
870
881
  add_to_latest_reconstructions=True,
871
882
  instanciate_class_only=False,
883
+ axis: NabuPlane = NabuPlane.XY,
872
884
  ) -> Optional[ResultsRun]:
873
885
  """
874
886
  # TODO: might need something like a context or an option "keep" slice in memory
@@ -882,8 +894,6 @@ def run_single_slice_reconstruction(
882
894
  :param local:
883
895
  :param stdout: file to redirect stdout
884
896
  :param stderr: file to redirect stderr
885
- :param bool ask_sinogram_registration: should we ask nabu to register sinogram
886
- :param bool ask_sinogram_load: should we ask nabu to load sinogram
887
897
  :param bool add_to_latest_reconstructions: if true add reconstructed slice to the latest reconstruction.
888
898
  We wan't to avoid this treatment for saaxis and sadeltebeta for example
889
899
  :param bool instanciate_class_only: if we don't want to run the SingleSliceRunner but only return them. Use case: we want to keep a hand on processing and it can be cancelled
@@ -892,6 +902,12 @@ def run_single_slice_reconstruction(
892
902
  """
893
903
  # TODO: remove local from the function signature
894
904
  target = Target.SLURM if cluster_config not in ({}, None) else Target.LOCAL
905
+ axis = NabuPlane.from_value(axis)
906
+ # FIXEME: nabu fails if outer_circle activated and if the axis != z
907
+ if axis != NabuPlane.XY and nabu_config.get("reconstruction", {}).get(
908
+ "clip_outer_circle", False
909
+ ):
910
+ nabu_config["reconstruction"]["clip_outer_circle"] = False
895
911
 
896
912
  if process_id is not None:
897
913
  try:
@@ -906,9 +922,8 @@ def run_single_slice_reconstruction(
906
922
  config=nabu_config,
907
923
  dry_run=dry_run,
908
924
  slice_index=slice_index,
925
+ axis=axis,
909
926
  target=target,
910
- ask_sinogram_registration=ask_sinogram_registration,
911
- ask_sinogram_load=ask_sinogram_load,
912
927
  cluster_config=cluster_config,
913
928
  add_to_latest_reconstructions=add_to_latest_reconstructions,
914
929
  process_name=process_name,
@@ -931,7 +946,7 @@ class NabuSliceMode(_Enum):
931
946
  OTHER = "other"
932
947
 
933
948
  @staticmethod
934
- def getSlices(slices, scan) -> tuple:
949
+ def getSlices(slices, scan, axis=NabuPlane.XY) -> tuple:
935
950
  res = []
936
951
  try:
937
952
  mode = NabuSliceMode.from_value(slices)
@@ -942,7 +957,13 @@ class NabuSliceMode(_Enum):
942
957
  pass
943
958
  else:
944
959
  if mode == mode.MIDDLE:
945
- n_slice = scan.dim_2 or 2048
960
+ axis = NabuPlane.from_value(axis)
961
+ if axis is NabuPlane.XY:
962
+ n_slice = scan.dim_2 or 2048
963
+ elif axis in (NabuPlane.YZ, NabuPlane.XZ):
964
+ n_slice = scan.dim_1 or 2048
965
+ else:
966
+ raise NotImplementedError(f"unknow axis {axis}")
946
967
  res.append(n_slice // 2)
947
968
  else:
948
969
  raise ValueError(
@@ -43,21 +43,27 @@ from processview.core.manager.manager import ProcessManager, DatasetState
43
43
  from processview.core.superviseprocess import SuperviseProcess
44
44
 
45
45
  from silx.io.utils import h5py_read_dataset
46
- from silx.utils.deprecation import deprecated_warning
47
-
48
- from tomoscan.io import HDF5File
46
+ from silx.io.utils import open as open_hdf5
47
+ from tomwer.core.utils.deprecation import deprecated_warning
49
48
 
50
49
  from tomwer.core.cluster.cluster import SlurmClusterConfiguration
51
50
  from tomwer.core.futureobject import FutureTomwerObject
51
+ from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
52
52
  from tomwer.core.process.task import Task
53
+ from tomwer.core.process.icat.gallery import (
54
+ IcatScreenshots,
55
+ deduce_dataset_gallery_location,
56
+ select_screenshot_from_volume,
57
+ )
53
58
  from tomwer.core.scan.edfscan import EDFTomoScan
54
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
59
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
55
60
  from tomwer.core.scan.scanbase import TomwerScanBase
56
61
  from tomwer.core.scan.scanfactory import ScanFactory
62
+ from tomwer.core.utils.dictutils import concatenate_dict
57
63
  from tomwer.core.utils.scanutils import data_identifier_to_scan
64
+ from tomwer.core.volume.volumefactory import VolumeFactory
58
65
  from tomwer.io.utils.h5pyutils import EntryReader
59
66
  from tomwer.utils import docstring
60
- from tomwer.core.utils import concatenate_dict
61
67
  from tomwer.io.utils import format_stderr_stdout
62
68
 
63
69
  from . import settings, utils
@@ -143,8 +149,8 @@ def run_volume_reconstruction(
143
149
  assert len(results) == 1, "only one volume should be reconstructed"
144
150
  res = results[0]
145
151
  # tag latest reconstructions
146
- if isinstance(res, ResultsLocalRun) and res.results_urls is not None:
147
- scan.set_latest_vol_reconstructions(res.results_urls)
152
+ if isinstance(res, ResultsLocalRun) and res.results_identifiers is not None:
153
+ scan.set_latest_vol_reconstructions(res.results_identifiers)
148
154
  # create future if needed
149
155
  if isinstance(res, ResultSlurmRun):
150
156
  future_tomo_obj = FutureTomwerObject(
@@ -269,8 +275,6 @@ class VolumeRunner(_NabuBaseReconstructor):
269
275
  self._process_config(
270
276
  config_to_dump=config_to_dump,
271
277
  config_file=conf_file,
272
- start_z=config_to_dump["reconstruction"]["start_z"],
273
- end_z=config_to_dump["reconstruction"]["end_z"],
274
278
  info="nabu volume reconstruction",
275
279
  file_format=config_slices["output"]["file_format"],
276
280
  process_name=self.process_name,
@@ -292,8 +296,8 @@ class VolumeRunner(_NabuBaseReconstructor):
292
296
  def process(self, fn):
293
297
  if fn.done() and not (fn.cancelled() or fn.exception()):
294
298
  # update reconstruction urls only if processing succeed.
295
- recons_urls = self.f_partial()
296
- self.scan.add_latest_vol_reconstructions(recons_urls)
299
+ recons_identifiers = self.f_partial()
300
+ self.scan.add_latest_vol_reconstructions(recons_identifiers)
297
301
 
298
302
  file_format = config_to_dump["output"]["file_format"]
299
303
  callback = functools.partial(
@@ -303,9 +307,7 @@ class VolumeRunner(_NabuBaseReconstructor):
303
307
  file_format=file_format,
304
308
  scan=self.scan,
305
309
  slice_index=None,
306
- start_z=config_to_dump["reconstruction"]["start_z"],
307
- end_z=config_to_dump["reconstruction"]["end_z"],
308
- expects_single_slice=False,
310
+ axis=NabuPlane.XY, # for volume we always reconstruct along XY plane
309
311
  )
310
312
 
311
313
  return (CallBack(callback, self.scan),)
@@ -323,17 +325,16 @@ class VolumeRunner(_NabuBaseReconstructor):
323
325
  if "postproc" in config:
324
326
  config["postproc"] = config["postproc"]
325
327
 
326
- if "start_z" in config:
327
- config["reconstruction"]["start_z"] = config["start_z"]
328
- del config["start_z"]
329
- if "end_z" in config:
330
- config["reconstruction"]["end_z"] = config["end_z"]
331
- del config["end_z"]
328
+ # make sure start_[x] and end_[x] come from config
329
+ for key in ("start_x", "end_x", "start_y", "end_y", "start_z", "end_z"):
330
+ if key in config:
331
+ config["reconstruction"][key] = config[key]
332
+ del config[key]
332
333
 
333
334
  return config, nabu_cfg_folder
334
335
 
335
336
  @docstring(_NabuBaseReconstructor)
336
- def _get_file_basename_reconstruction(self, pag, db, ctf):
337
+ def _get_file_basename_reconstruction(self, pag, db, ctf, axis):
337
338
  """
338
339
 
339
340
  :param TomwerScanBase scan: scan reconstructed
@@ -342,16 +343,17 @@ class VolumeRunner(_NabuBaseReconstructor):
342
343
  entire volume
343
344
  :param bool pag: is it a paganin reconstruction
344
345
  :param int db: delta / beta parameter
346
+ :param axis: axis over which the reconstruction goes. For volume always expected to be z. So ignored in the function
345
347
  :return: basename of the file reconstructed (without any extension)
346
348
  """
347
349
  assert type(db) in (int, type(None))
348
350
  assert not pag == ctf == True, "cannot ask for both pag and ctf active"
349
- if isinstance(self.scan, HDF5TomoScan):
351
+ if isinstance(self.scan, NXtomoScan):
350
352
  basename, _ = os.path.splitext(self.scan.master_file)
351
353
  basename = os.path.basename(basename)
352
354
  try:
353
355
  # if there is more than one entry in the file append the entry name to the file basename
354
- with HDF5File(self.scan.master_file, mode="r") as h5f:
356
+ with open_hdf5(self.scan.master_file) as h5f:
355
357
  if len(h5f.keys()) > 1:
356
358
  basename = "_".join((basename, self.scan.entry.strip("/")))
357
359
  except Exception:
@@ -371,7 +373,7 @@ class NabuVolumeTask(
371
373
  Task,
372
374
  SuperviseProcess,
373
375
  input_names=("data", "nabu_params"),
374
- output_names=("data", "volumes", "future_tomo_obj"),
376
+ output_names=("data", "volumes", "future_tomo_obj", "screenshots"),
375
377
  optional_input_names=(
376
378
  "dry_run",
377
379
  "nabu_extra_params", # some parameter that must update 'nabu_params' before launching the reconstruction. Such as z range...
@@ -462,8 +464,8 @@ class NabuVolumeTask(
462
464
  future_tomo_obj = None
463
465
  else:
464
466
  # tag latest reconstructions
465
- if isinstance(res, ResultsLocalRun) and res.results_urls is not None:
466
- scan.set_latest_vol_reconstructions(res.results_urls)
467
+ if isinstance(res, ResultsLocalRun) and res.results_identifiers is not None:
468
+ scan.set_latest_vol_reconstructions(res.results_identifiers)
467
469
  # create future if needed
468
470
  if isinstance(res, ResultSlurmRun):
469
471
  future_tomo_obj = FutureTomwerObject(
@@ -527,6 +529,31 @@ class NabuVolumeTask(
527
529
  self.outputs.volumes = scan.latest_vol_reconstructions
528
530
  self.outputs.future_tomo_obj = future_tomo_obj
529
531
 
532
+ # build screenshots
533
+ if scan.latest_vol_reconstructions is not None:
534
+ try:
535
+ screenshots = {}
536
+ [
537
+ screenshots.update(
538
+ select_screenshot_from_volume(
539
+ VolumeFactory.create_tomo_object_from_identifier(
540
+ rec_identifier
541
+ )
542
+ )
543
+ )
544
+ for rec_identifier in scan.latest_vol_reconstructions
545
+ ]
546
+ except Exception as e:
547
+ _logger.error(f"screenshot creation failed. Error is {e}")
548
+ else:
549
+ self.outputs.screenshots = IcatScreenshots(
550
+ data_dir=deduce_dataset_gallery_location(scan),
551
+ screenshots=screenshots,
552
+ scan=scan,
553
+ )
554
+ else:
555
+ self.outputs.screenshots = tuple()
556
+
530
557
  def set_configuration(self, configuration: dict) -> None:
531
558
  Task.set_configuration(self, configuration=configuration)
532
559
  if "dry_run" in configuration:
@@ -552,7 +579,7 @@ class NabuVolumeTask(
552
579
  with EntryReader(scan.process_file_url) as h5f:
553
580
  latest_nabu_node = Task.get_most_recent_process(h5f, NabuVolumeTask)
554
581
  path = "configuration/reconstruction/rotation_axis_position"
555
- if path in latest_nabu_node:
582
+ if latest_nabu_node is not None and path in latest_nabu_node:
556
583
  return h5py_read_dataset(latest_nabu_node[path])
557
584
 
558
585
  def cancel(self):
@@ -0,0 +1,9 @@
1
+ """Define nabu Axis"""
2
+
3
+ from silx.utils.enum import Enum as _Enum
4
+
5
+
6
+ class NabuPlane(_Enum):
7
+ YZ = "YZ"
8
+ XZ = "XZ"
9
+ XY = "XY"
@@ -33,8 +33,6 @@ import logging
33
33
  _logger = logging.getLogger(__name__)
34
34
 
35
35
 
36
- NABU_FILE_PER_GROUP = 100
37
-
38
36
  NABU_CONFIG_FILE_EXTENSION = ".cfg"
39
37
 
40
38
  NABU_CFG_FILE_FOLDER = "nabu_cfg_files"
@@ -60,3 +58,5 @@ else:
60
58
 
61
59
 
62
60
  NABU_CAST_APP_PATH = "nabu.app.cast_volume"
61
+
62
+ NABU_MULTICOR_PATH = "nabu.app.multicor"