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
@@ -107,10 +107,10 @@ class SerieWidget(qt.QTabWidget):
107
107
 
108
108
  # conenct signal / slot
109
109
  self._historyWidget.sigEditSerie.connect(self._serieEditionRequested)
110
- self._historyWidget.sigSerieSend.connect(self._repeatSerieSend)
110
+ self._historyWidget.sigSerieSend.connect(self.sigSerieSend)
111
111
  self._historyWidget.sigHistoryUpdated.connect(self._repeatHistoryUpdated)
112
112
  self._serieDefinitionWidget.sigSerieChanged.connect(self._repeatSerieChanged)
113
- self._serieDefinitionWidget.sigSerieSend.connect(self._repeatSerieSend)
113
+ self._serieDefinitionWidget.sigSerieSend.connect(self.sigSerieSend)
114
114
  self._serieDefinitionWidget.sigSerieSend.connect(self._historyWidget.addSerie)
115
115
 
116
116
  def getHistoryWidget(self):
@@ -143,9 +143,6 @@ class SerieWidget(qt.QTabWidget):
143
143
  def _repeatSerieChanged(self, *args, **kwargs):
144
144
  self.sigCurrentSerieChanged.emit()
145
145
 
146
- def _repeatSerieSend(self, serie: Serie):
147
- self.sigSerieSend.emit(serie)
148
-
149
146
  def _repeatHistoryUpdated(self, *args, **kwargs):
150
147
  self.sigHistoryChanged.emit()
151
148
 
@@ -186,9 +183,7 @@ class SerieDefinition(qt.QWidget):
186
183
 
187
184
  # connect signal / slot
188
185
  self._modeCB.currentIndexChanged.connect(self._updateVisibility)
189
- self._manualDefWidget._newSerieWidget.sigUpdated.connect(
190
- self._repeatSerieChanged
191
- )
186
+ self._manualDefWidget._newSerieWidget.sigUpdated.connect(self.sigSerieChanged)
192
187
 
193
188
  # set up
194
189
  self._updateVisibility()
@@ -217,12 +212,6 @@ class SerieDefinition(qt.QWidget):
217
212
  def getAutoDefinitionWidget(self):
218
213
  return self._automaticDefWidget
219
214
 
220
- def _repeatSerieChanged(self, *args, **kwargs):
221
- self.sigSerieChanged.emit()
222
-
223
- def _repeatSerieSend(self, serie: Serie):
224
- self.sigSerieSend.emit(serie)
225
-
226
215
  def createManualSerie(self):
227
216
  self._manualDefWidget.createSerie()
228
217
 
@@ -651,7 +640,7 @@ class NewSerieWidget(qt.QWidget):
651
640
 
652
641
  # Signal / slot connection
653
642
  self._serieTree.itemChanged.connect(self._handleItemUpdate)
654
- self._serieTree.sigUpdated.connect(self._repeatUpdateSignal)
643
+ self._serieTree.sigUpdated.connect(self.sigUpdated)
655
644
  self._nameQLE.textChanged.connect(self._nameChangedOnQLE)
656
645
 
657
646
  def setSerie(self, serie: Serie) -> None:
@@ -674,9 +663,6 @@ class NewSerieWidget(qt.QWidget):
674
663
  self.blockSignals(old)
675
664
  self.sigUpdated.emit()
676
665
 
677
- def _repeatUpdateSignal(self):
678
- self.sigUpdated.emit()
679
-
680
666
  def addTomoObjToCurrentSerie(self, tomo_obj: TomwerObject):
681
667
  assert isinstance(
682
668
  tomo_obj, TomwerObject
@@ -726,7 +712,7 @@ class SerieManualDefinitionDialog(qt.QDialog):
726
712
 
727
713
  # connect signal / slot
728
714
  self._newSerieWidget.sigNameChanged.connect(self._nameChanged)
729
- self._newSerieWidget.sigUpdated.connect(self._repeatUpdateSignal)
715
+ self._newSerieWidget.sigUpdated.connect(self.sigUpdated)
730
716
  self._addScanButton.clicked.connect(self.addScanFromFileDialog)
731
717
  self._removeSelectedButton.clicked.connect(self.removeSelectedTomoObjs)
732
718
  self._clearButton.clicked.connect(self.clearSerie)
@@ -742,9 +728,6 @@ class SerieManualDefinitionDialog(qt.QDialog):
742
728
  serieTree.setSerieName(name=new_name)
743
729
  self.sigUpdated.emit()
744
730
 
745
- def _repeatUpdateSignal(self):
746
- self.sigUpdated.emit()
747
-
748
731
  def setSerieName(self, name: str):
749
732
  self._newSerieWidget.setSerieName(name=name)
750
733
 
@@ -1,5 +1,5 @@
1
1
  from tomwer.tests.conftest import qtapp # noqa F401
2
- from tomwer.gui.control.email import Emailwidget
2
+ from tomwer.gui.control.emailnotifier import Emailwidget
3
3
 
4
4
 
5
5
  def test_Emailwidget(qtapp): # noqa F811
@@ -37,7 +37,8 @@ import time
37
37
  import pytest
38
38
  from silx.gui.utils.testutils import TestCaseQt
39
39
 
40
- from tomwer.core import settings, utils
40
+ from tomwer.core import settings
41
+ from tomwer.core.utils.lbsram import mock_low_memory, is_low_on_memory
41
42
  from tomwer.core.process.control.scanvalidator import ScanValidatorP
42
43
  from tomwer.core.scan.edfscan import EDFTomoScan
43
44
  from tomwer.core.utils.scanutils import MockEDF
@@ -57,7 +58,7 @@ class TestScanValidator(TestCaseQt):
57
58
  NB_SCANS = 2
58
59
 
59
60
  def tearDown(self):
60
- utils.mockLowMemory(False)
61
+ mock_low_memory(False)
61
62
 
62
63
  @classmethod
63
64
  def setUpClass(cls):
@@ -81,7 +82,7 @@ class TestScanValidator(TestCaseQt):
81
82
  shutil.rmtree(f)
82
83
 
83
84
  @pytest.mark.skipif(
84
- (settings.isOnLbsram() and utils.isLowOnMemory(settings.get_lbsram_path())),
85
+ (settings.isOnLbsram() and is_low_on_memory(settings.get_lbsram_path())),
85
86
  reason="Lbsram already overloaded",
86
87
  )
87
88
  def testMemoryReleaseLoop(self):
@@ -102,11 +103,11 @@ class TestScanValidator(TestCaseQt):
102
103
  time.sleep(self.LOOP_MEM_RELEASER_DURATION * 2)
103
104
 
104
105
  add_all_scans()
105
- utils.mockLowMemory(True)
106
+ mock_low_memory(True)
106
107
  my_wait()
107
108
  self.assertEqual(len(self.scanValidator._scans), 0)
108
109
 
109
- utils.mockLowMemory(False)
110
+ mock_low_memory(False)
110
111
  add_all_scans()
111
112
  my_wait()
112
113
  self.assertEqual(len(self.scanValidator._scans), self.NB_SCANS)
@@ -5,7 +5,7 @@ import numpy
5
5
  from silx.gui import qt
6
6
  from silx.gui.utils.testutils import TestCaseQt
7
7
 
8
- from tomwer.core.utils.scanutils import MockHDF5
8
+ from tomwer.core.utils.scanutils import MockNXtomo
9
9
  from tomwer.core.volume.hdf5volume import HDF5Volume
10
10
  from tomwer.gui.control.singletomoobj import SingleTomoObj
11
11
 
@@ -29,12 +29,12 @@ class TestSingletomoObj(TestCaseQt):
29
29
  self.volume.save()
30
30
 
31
31
  self._scan_file_path = os.path.join(self._tempdir, "scan.nx")
32
- self.scan_hdf5 = MockHDF5(
32
+ self.scan_hdf5 = MockNXtomo(
33
33
  scan_path=self._scan_file_path,
34
34
  n_proj=10,
35
35
  n_ini_proj=10,
36
36
  create_ini_dark=False,
37
- create_ini_ref=False,
37
+ create_ini_flat=False,
38
38
  dim=10,
39
39
  ).scan
40
40
 
@@ -0,0 +1,8 @@
1
+ from silx.utils.enum import Enum as _Enum
2
+
3
+
4
+ class DisplayMode(_Enum):
5
+ """possible display mode for the tomo object"""
6
+
7
+ URL = "url"
8
+ SHORT = "short"
@@ -34,7 +34,7 @@ from silx.gui import qt
34
34
 
35
35
  from tomwer.core.scan.blissscan import BlissScan
36
36
  from tomwer.core.scan.edfscan import EDFTomoScan
37
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
37
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
38
38
 
39
39
 
40
40
  class DatasetGeneratorDialog(qt.QDialog):
@@ -116,13 +116,13 @@ class DatasetGeneratorConfig(qt.QWidget):
116
116
  self._typeCB = qt.QComboBox(self)
117
117
  for _typeClass in (
118
118
  EDFTomoScan,
119
- HDF5TomoScan,
119
+ NXtomoScan,
120
120
  BlissScan,
121
121
  ):
122
122
  self._typeCB.addItem(_typeClass.__name__)
123
123
  self.layout().addWidget(qt.QLabel("type", self), 0, 0, 1, 1)
124
124
  self.layout().addWidget(self._typeCB, 0, 1, 1, 2)
125
- txt_index = self._typeCB.findText(HDF5TomoScan.__name__)
125
+ txt_index = self._typeCB.findText(NXtomoScan.__name__)
126
126
  self._typeCB.setCurrentIndex(txt_index)
127
127
 
128
128
  # generation timeout
@@ -36,11 +36,11 @@ from silx.gui import qt
36
36
  from silx.gui.dialog.DataFileDialog import DataFileDialog
37
37
  from silx.io.url import DataUrl
38
38
  from silx.io.utils import h5py_read_dataset
39
- from tomoscan.esrf.scan.hdf5scan import ImageKey
40
- from tomoscan.io import HDF5File
39
+ from silx.io.utils import open as open_hdf5
40
+ from nxtomo.nxobject.nxdetector import ImageKey
41
41
 
42
42
  import tomwer.core.utils.nxtomoutils as nxtomo_utils
43
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
43
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
44
44
  from tomwer.io.utils import get_default_directory
45
45
 
46
46
  _logger = logging.getLogger(__name__)
@@ -67,11 +67,8 @@ class _DarkOrFlatUrl(qt.QWidget):
67
67
 
68
68
  # connect signal / slot
69
69
  self._qle.editingFinished.connect(self._tryUpdateOptions)
70
- self._qle.editingFinished.connect(self._editingFinished)
71
- self._optionsCB.currentIndexChanged.connect(self._editingFinished)
72
-
73
- def _editingFinished(self):
74
- self.editingFinished.emit()
70
+ self._qle.editingFinished.connect(self.editingFinished)
71
+ self._optionsCB.currentIndexChanged.connect(self.editingFinished)
75
72
 
76
73
  def setUrl(self, url):
77
74
  """
@@ -86,7 +83,7 @@ class _DarkOrFlatUrl(qt.QWidget):
86
83
  url = self._redirectDataPath(url, logger=_logger)
87
84
 
88
85
  def dataset_invalid(url):
89
- with HDF5File(url.file_path(), mode="r") as h5s:
86
+ with open_hdf5(url.file_path()) as h5s:
90
87
  if not isinstance(h5s[url.data_path()], h5py.Dataset):
91
88
  return True
92
89
  return False
@@ -102,7 +99,7 @@ class _DarkOrFlatUrl(qt.QWidget):
102
99
  self._qle.setText(url.path())
103
100
  self._updateOptions(url)
104
101
  self.blockSignals(old)
105
- self._editingFinished()
102
+ self.editingFinished.emit()
106
103
 
107
104
  def setSerie(self, serie):
108
105
  type_name = self._type.name.lower().replace("_", " ")
@@ -116,10 +113,10 @@ class _DarkOrFlatUrl(qt.QWidget):
116
113
 
117
114
  def _redirectDataPath(self, url, logger=None):
118
115
  try:
119
- with HDF5File(url.file_path(), mode="r") as h5s:
116
+ with open_hdf5(url.file_path()) as h5s:
120
117
  node = h5s[url.data_path()]
121
118
 
122
- if HDF5TomoScan.entry_is_nx_tomo(node):
119
+ if NXtomoScan.entry_is_nx_tomo(node):
123
120
  if (
124
121
  "detector" in node["instrument"]
125
122
  and "data" in node["instrument"]["detector"]
@@ -133,7 +130,7 @@ class _DarkOrFlatUrl(qt.QWidget):
133
130
  (url.data_path(), "instrument", "detector", "data")
134
131
  )
135
132
  url = DataUrl(file_path=url.file_path(), data_path=data_path)
136
- elif HDF5TomoScan.is_nxdetector(node):
133
+ elif NXtomoScan.is_nxdetector(node):
137
134
  if "data" in node:
138
135
  if logger:
139
136
  _logger.info(
@@ -191,10 +188,10 @@ class _DarkOrFlatUrl(qt.QWidget):
191
188
  def _getImageKey(self, url):
192
189
  # if we are on a 'detector / data dataset' then we can try to reach
193
190
  # image_key information
194
- with HDF5File(url.file_path(), mode="r") as h5s:
191
+ with open_hdf5(url.file_path()) as h5s:
195
192
  dataset = h5s[url.data_path()]
196
193
  grp_parent = dataset.parent
197
- if grp_parent is not None and HDF5TomoScan.is_nxdetector(grp_parent):
194
+ if grp_parent is not None and NXtomoScan.is_nxdetector(grp_parent):
198
195
  if "image_key" in grp_parent:
199
196
  return h5py_read_dataset(grp_parent["image_key"])
200
197
  return None
@@ -319,17 +316,14 @@ class DarkRefPatchWidget(qt.QWidget):
319
316
  self._efCB.toggled.connect(self._toggleEF)
320
317
 
321
318
  # connect QLE modifications
322
- self._sdQLE.editingFinished.connect(self._configurationChanged)
323
- self._sdCB.toggled.connect(self._configurationChanged)
324
- self._sfQLE.editingFinished.connect(self._configurationChanged)
325
- self._sfCB.toggled.connect(self._configurationChanged)
326
- self._efQLE.editingFinished.connect(self._configurationChanged)
327
- self._efCB.toggled.connect(self._configurationChanged)
328
- self._edQLE.editingFinished.connect(self._configurationChanged)
329
- self._edCB.toggled.connect(self._configurationChanged)
330
-
331
- def _configurationChanged(self):
332
- self.sigConfigurationChanged.emit()
319
+ self._sdQLE.editingFinished.connect(self.sigConfigurationChanged)
320
+ self._sdCB.toggled.connect(self.sigConfigurationChanged)
321
+ self._sfQLE.editingFinished.connect(self.sigConfigurationChanged)
322
+ self._sfCB.toggled.connect(self.sigConfigurationChanged)
323
+ self._efQLE.editingFinished.connect(self.sigConfigurationChanged)
324
+ self._efCB.toggled.connect(self.sigConfigurationChanged)
325
+ self._edQLE.editingFinished.connect(self.sigConfigurationChanged)
326
+ self._edCB.toggled.connect(self.sigConfigurationChanged)
333
327
 
334
328
  def _selectSDDataset(self):
335
329
  self._selectDataset("start dark", self._sdQLE)
@@ -35,10 +35,10 @@ from collections.abc import Iterable
35
35
  from typing import Union
36
36
 
37
37
  from silx.gui import qt
38
- from tomoscan.esrf.scan.hdf5scan import ImageKey as _ImageKey
38
+ from nxtomo.nxobject.nxdetector import ImageKey as _ImageKey
39
39
 
40
40
  from tomwer.core.process.edit.imagekeyeditor import IMAGE_KEYS
41
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
41
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
42
42
 
43
43
  _logger = logging.getLogger(__name__)
44
44
 
@@ -93,7 +93,7 @@ class ImageKeyDialog(qt.QDialog):
93
93
  def setScan(self, scan):
94
94
  """
95
95
 
96
- :param HDF5TomoScan scan: scan to be edited
96
+ :param NXtomoScan scan: scan to be edited
97
97
  """
98
98
  self._widget.setScan(scan)
99
99
 
@@ -120,7 +120,7 @@ class ImageKeyWindow(qt.QMainWindow):
120
120
  def setScan(self, scan) -> None:
121
121
  """
122
122
 
123
- :param HDF5TomoScan scan: scan to be edited
123
+ :param NXtomoScan scan: scan to be edited
124
124
  """
125
125
  self._mainWindow.setScan(scan=scan)
126
126
  self._editorControl.setScan(scan=scan)
@@ -213,7 +213,7 @@ class _ImageKeyEditor(qt.QDialog):
213
213
  self._selectionModeCB.currentTextChanged.connect(
214
214
  self._selectionWidget.setSelectionMode
215
215
  )
216
- self._buttons.button(qt.QDialogButtonBox.Ok).clicked.connect(self._apply)
216
+ self._buttons.button(qt.QDialogButtonBox.Ok).clicked.connect(self.sigApply)
217
217
 
218
218
  def getUpgradeToImagKey(self) -> str:
219
219
  """
@@ -243,9 +243,6 @@ class _ImageKeyEditor(qt.QDialog):
243
243
  else:
244
244
  raise NotImplementedError("Not implemented")
245
245
 
246
- def _apply(self):
247
- self.sigApply.emit()
248
-
249
246
  def setScan(self, scan):
250
247
  self._selectionWidget.setScan(scan=scan)
251
248
  if scan is not None:
@@ -450,7 +447,7 @@ class _ImageKeyList(qt.QTableWidget):
450
447
  """
451
448
  Update the QTableWidget for the provided frames
452
449
 
453
- :param Iterable frames: Iterable of tomoscan.esrf.scan.HDF5TomoScan.Frame
450
+ :param Iterable frames: Iterable of tomoscan.esrf.scan.NXtomoScan.Frame
454
451
  :param dict frames_new_keys: dictionary with frame edited. key is frame
455
452
  index. Value is the new `image_key` value
456
453
  """
@@ -522,6 +519,7 @@ class _ImageKeyList(qt.QTableWidget):
522
519
  my_list = modifications
523
520
  to_apply = {}
524
521
  for frame_index in my_list:
522
+ assert isinstance(frame_index, int), "frame_index should be an int"
525
523
  to_apply[frame_index] = new_image_key
526
524
  if frame_index in self._imageKeyComboboxes:
527
525
  self._imageKeyComboboxes[frame_index].setImageKey(new_image_key)
@@ -551,12 +549,13 @@ class _ImageKeyList(qt.QTableWidget):
551
549
  else:
552
550
  self.hideRow(i)
553
551
 
554
- def notify_modified(self, frame_index) -> None:
552
+ def notify_modified(self, frame_index: int) -> None:
555
553
  """
556
554
  Update list of modification and emit sigKeyUpdated
557
555
 
558
556
  :param int frame_index:
559
557
  """
558
+ assert isinstance(frame_index, int), "frame index should be an int"
560
559
  frame_row = self._getFrameRowIndex(frame_index)
561
560
  if frame_row is not None:
562
561
  new_image_key = self._imageKeyComboboxes[frame_index].currentText()
@@ -627,9 +626,9 @@ class _ImageKeyListFiltered(qt.QWidget):
627
626
  return self._filterCB.currentText()
628
627
 
629
628
  def setScan(self, scan):
630
- if not isinstance(scan, HDF5TomoScan):
629
+ if not isinstance(scan, NXtomoScan):
631
630
  raise TypeError(
632
- f"scan should be an instance of {HDF5TomoScan}. {type(scan)} provided"
631
+ f"scan should be an instance of {NXtomoScan}. {type(scan)} provided"
633
632
  )
634
633
  self.__frames_modifications = {}
635
634
  self._scan = weakref.ref(scan)
@@ -1,17 +1,26 @@
1
1
  import logging
2
2
  import weakref
3
3
  from typing import Optional
4
+ from functools import lru_cache as cache
4
5
 
5
6
  import h5py
6
7
  import numpy
7
8
  from silx.gui import qt
8
9
  from silx.io.utils import h5py_read_dataset
9
- from tomoscan.esrf.scan.hdf5scan import ImageKey
10
- from tomoscan.io import HDF5File
11
- from tomoscan.nexus.paths.nxtomo import get_paths as get_nexus_paths
12
- from tomoscan.scanbase import _FOV
10
+ from silx.io.dictdump import dicttonx
13
11
 
14
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
12
+ from tomoscan.io import HDF5File
13
+ from nxtomo.paths.nxtomo import get_paths as get_nexus_paths
14
+ from nxtomo.nxobject.nxdetector import ImageKey
15
+ from nxtomo.nxobject.nxdetector import FOV
16
+ from nxtomo.nxobject.nxtransformations import NXtransformations
17
+ from nxtomo.utils.transformation import (
18
+ build_matrix,
19
+ UDDetTransformation,
20
+ LRDetTransformation,
21
+ )
22
+
23
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
15
24
  from tomwer.gui.utils.buttons import PadlockButton
16
25
  from tomwer.gui.utils.scandescription import ScanNameLabelAndShape
17
26
  from tomwer.gui.utils.unitsystem import MetricEntry
@@ -149,7 +158,7 @@ class NXtomoEditor(qt.QWidget):
149
158
  self._fieldOfViewQTWI = qt.QTreeWidgetItem(self._detectorQTWI)
150
159
  self._fieldOfViewQTWI.setText(0, "field of view")
151
160
  self._fieldOfViewCB = qt.QComboBox(self)
152
- for value in _FOV.values():
161
+ for value in FOV.values():
153
162
  self._fieldOfViewCB.addItem(value)
154
163
  self._tree.setItemWidget(self._fieldOfViewQTWI, 1, self._fieldOfViewCB)
155
164
  self._editableWidgets.append(self._fieldOfViewCB)
@@ -235,9 +244,9 @@ class NXtomoEditor(qt.QWidget):
235
244
  def setScan(self, scan):
236
245
  if scan is None:
237
246
  self._scan = scan
238
- elif not isinstance(scan, HDF5TomoScan):
247
+ elif not isinstance(scan, NXtomoScan):
239
248
  raise TypeError(
240
- f"{scan} is expected to be an instance of {HDF5TomoScan}. Not {type(scan)}"
249
+ f"{scan} is expected to be an instance of {NXtomoScan}. Not {type(scan)}"
241
250
  )
242
251
  else:
243
252
  self._scan = weakref.ref(scan)
@@ -281,8 +290,8 @@ class NXtomoEditor(qt.QWidget):
281
290
  else:
282
291
  self._updateTranslations(scan=scan)
283
292
 
284
- def _updateTranslations(self, scan: HDF5TomoScan):
285
- assert isinstance(scan, HDF5TomoScan)
293
+ def _updateTranslations(self, scan: NXtomoScan):
294
+ assert isinstance(scan, NXtomoScan)
286
295
 
287
296
  # note: for now and in order to allow edition we expect to have at most a unique value. Will fail for helicoidal
288
297
  def reduce(values):
@@ -307,17 +316,61 @@ class NXtomoEditor(qt.QWidget):
307
316
  def _updateFieldOfView(self, scan):
308
317
  if not self._fieldOfViewLB.isLocked():
309
318
  # if in ''auto mode: we want to overwrite the NXtomo existing value by the one of the GUI
310
- idx = self._fieldOfViewCB.findText(
311
- _FOV.from_value(scan.field_of_view).value
312
- )
319
+ idx = self._fieldOfViewCB.findText(FOV.from_value(scan.field_of_view).value)
313
320
  if idx > 0:
314
321
  self._fieldOfViewCB.setCurrentIndex(idx)
315
322
 
323
+ @staticmethod
324
+ @cache(maxsize=None)
325
+ def _get_UD_flip_matrix():
326
+ return UDDetTransformation().as_matrix()
327
+
328
+ @staticmethod
329
+ @cache(maxsize=None)
330
+ def _get_LR_flip_matrix():
331
+ return LRDetTransformation().as_matrix()
332
+
333
+ @staticmethod
334
+ @cache(maxsize=None)
335
+ def _get_UD_AND_LR_flip_matrix():
336
+ return numpy.matmul(
337
+ NXtomoEditor._get_UD_flip_matrix(),
338
+ NXtomoEditor._get_LR_flip_matrix(),
339
+ )
340
+
316
341
  def _updateFlipped(self, scan):
317
- if (not self._xFlippedLB.isLocked()) and scan.x_flipped is not None:
318
- self._xFlippedCB.setChecked(scan.x_flipped)
319
- if (not self._yFlippedLB.isLocked()) and scan.y_flipped is not None:
320
- self._yFlippedCB.setChecked(scan.y_flipped)
342
+ transformations = list(scan.get_detector_transformations(tuple()))
343
+ transformation_matrix_det_space = build_matrix(transformations)
344
+ if transformation_matrix_det_space is None or numpy.allclose(
345
+ transformation_matrix_det_space, numpy.identity(3)
346
+ ):
347
+ flip_ud = False
348
+ flip_lr = False
349
+ elif numpy.array_equal(
350
+ transformation_matrix_det_space, NXtomoEditor._get_UD_flip_matrix()
351
+ ):
352
+ flip_ud = True
353
+ flip_lr = False
354
+ elif numpy.allclose(
355
+ transformation_matrix_det_space, NXtomoEditor._get_LR_flip_matrix()
356
+ ):
357
+ flip_ud = False
358
+ flip_lr = True
359
+ elif numpy.allclose(
360
+ transformation_matrix_det_space, NXtomoEditor._get_UD_AND_LR_flip_matrix()
361
+ ):
362
+ flip_ud = True
363
+ flip_lr = True
364
+ else:
365
+ flip_ud = None
366
+ flip_lr = None
367
+ _logger.warning(
368
+ "detector transformations provided not handled... For now only handle up-down flip as left-right flip"
369
+ )
370
+ if (not self._xFlippedLB.isLocked()) and flip_lr is not None:
371
+ self._xFlippedCB.setChecked(flip_lr)
372
+ if (not self._yFlippedLB.isLocked()) and flip_ud is not None:
373
+ self._yFlippedCB.setChecked(flip_ud)
321
374
 
322
375
  def _updateDistance(self, scan):
323
376
  if not self._distanceLB.isLocked():
@@ -325,14 +378,14 @@ class NXtomoEditor(qt.QWidget):
325
378
  self._distanceMetricEntry.setValue(scan.distance)
326
379
 
327
380
  def _updateEnergy(self, scan):
328
- assert isinstance(scan, HDF5TomoScan)
381
+ assert isinstance(scan, NXtomoScan)
329
382
  if not self._energyLockerLB.isLocked():
330
383
  # if in ''auto mode: we want to overwrite the NXtomo existing value by the one of the GUI
331
384
  energy = scan.energy
332
385
  self._energyEntry.setValue(energy)
333
386
 
334
387
  def _updatePixelSize(self, scan):
335
- assert isinstance(scan, HDF5TomoScan)
388
+ assert isinstance(scan, NXtomoScan)
336
389
  if not self._xPixelSizeLB.isLocked():
337
390
  x_pixel_size = scan.x_pixel_size
338
391
  self._xPixelSizeMetricEntry.setValue(x_pixel_size)
@@ -433,7 +486,7 @@ class NXtomoEditor(qt.QWidget):
433
486
  _logger.warning("no scan found to be saved")
434
487
  return
435
488
  nexus_paths = get_nexus_paths(scan.nexus_version)
436
- assert isinstance(scan, HDF5TomoScan)
489
+ assert isinstance(scan, NXtomoScan)
437
490
  with HDF5File(scan.master_file, mode="a") as h5f:
438
491
  entry = h5f[scan.entry]
439
492
  # overwrite energy
@@ -503,37 +556,49 @@ class NXtomoEditor(qt.QWidget):
503
556
  name="field of view",
504
557
  expected_type=str,
505
558
  )
506
- # overwrite x flipped
507
- self.__write_to_file(
508
- entry=entry,
509
- path="/".join(
559
+
560
+ # solve NXtranformations
561
+ nx_transformations = NXtransformations()
562
+ if self._xFlippedCB.isChecked():
563
+ nx_transformations.add_transformation(LRDetTransformation())
564
+ if self._yFlippedCB.isChecked():
565
+ nx_transformations.add_transformation(UDDetTransformation())
566
+
567
+ nx_dict = nx_transformations.to_nx_dict(
568
+ nexus_path_version=scan.nexus_version,
569
+ data_path="/".join(
510
570
  (
511
571
  nexus_paths.INSTRUMENT_PATH,
512
572
  nexus_paths.nx_instrument_paths.DETECTOR_PATH,
513
- nexus_paths.nx_detector_paths.X_FLIPPED,
514
573
  )
515
574
  ),
516
- value=self._xFlippedCB.isChecked(),
517
- name="x flipped",
518
- expected_type=bool,
575
+ solve_empty_dependency=True,
519
576
  )
520
- # overwrite y flipped
521
- self.__write_to_file(
522
- entry=entry,
523
- path="/".join(
524
- (
525
- nexus_paths.INSTRUMENT_PATH,
526
- nexus_paths.nx_instrument_paths.DETECTOR_PATH,
527
- nexus_paths.nx_detector_paths.Y_FLIPPED,
528
- )
577
+ detector_transformation_path = "/".join(
578
+ (
579
+ nexus_paths.INSTRUMENT_PATH,
580
+ nexus_paths.nx_instrument_paths.DETECTOR_PATH,
581
+ nexus_paths.nx_detector_paths.NX_TRANSFORMATIONS,
529
582
  ),
530
- value=self._yFlippedCB.isChecked(),
531
- name="y flipped",
532
- expected_type=bool,
533
583
  )
534
- # clear caches to make sure all modifications will be considered
535
- scan.clear_caches()
536
- scan.clear_frames_caches()
584
+ if detector_transformation_path in entry:
585
+ del entry[detector_transformation_path]
586
+
587
+ detector_transformation_path = "/".join(
588
+ (scan.entry, detector_transformation_path)
589
+ )
590
+
591
+ dicttonx(
592
+ nx_dict,
593
+ h5file=scan.master_file,
594
+ h5path=detector_transformation_path,
595
+ update_mode="replace",
596
+ mode="a",
597
+ )
598
+
599
+ # clear caches to make sure all modifications will be considered
600
+ scan.clear_caches()
601
+ scan.clear_frames_caches()
537
602
 
538
603
  @staticmethod
539
604
  def _newValueIsExistingValue(dataset: h5py.Dataset, new_value, units):
@@ -557,7 +622,9 @@ class NXtomoEditor(qt.QWidget):
557
622
  return False
558
623
 
559
624
  @staticmethod
560
- def __write_to_file(entry, path, value, name, expected_type, n_value=1, units=None):
625
+ def __write_to_file(
626
+ entry: h5py.Group, path: str, value, name, expected_type, n_value=1, units=None
627
+ ):
561
628
  if path is None:
562
629
  # if the path does not exists (no handled by this version of nexus for example)
563
630
  return
@@ -1,9 +1,10 @@
1
1
  from typing import Optional
2
2
  import h5py
3
3
  from silx.gui import qt
4
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
4
+ from silx.io.utils import open as open_hdf5
5
+
6
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
5
7
  from tomwer.gui import icons
6
- from tomoscan.io import HDF5File
7
8
 
8
9
 
9
10
  class NXtomoProxyWarmer(qt.QWidget):
@@ -40,17 +41,17 @@ class NXtomoProxyWarmer(qt.QWidget):
40
41
  # set up
41
42
  self.setScan(None)
42
43
 
43
- def setScan(self, scan: Optional[HDF5TomoScan]):
44
+ def setScan(self, scan: Optional[NXtomoScan]):
44
45
  if scan is None:
45
46
  self._activateWarning(False)
46
- elif isinstance(scan, HDF5TomoScan):
47
- with HDF5File(scan.master_file, mode="r") as h5f:
47
+ elif isinstance(scan, NXtomoScan):
48
+ with open_hdf5(scan.master_file) as h5f:
48
49
  entry = h5f.get(
49
50
  name=scan.entry, getclass=True, getlink=True, default=None
50
51
  )
51
52
  self._activateWarning(entry in (h5py.ExternalLink, h5py.SoftLink))
52
53
  else:
53
- raise TypeError(f"{scan} is expected to be an instance of {HDF5TomoScan}")
54
+ raise TypeError(f"{scan} is expected to be an instance of {NXtomoScan}")
54
55
 
55
56
  def _activateWarning(self, activate: bool):
56
57
  self._warningIcon.setVisible(activate)