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
@@ -29,8 +29,10 @@ __date__ = "23/03/2021"
29
29
 
30
30
 
31
31
  from silx.gui import qt
32
+ from functools import partial
32
33
 
33
34
  from tomwer.gui import icons as tomwer_icons
35
+ from tomwer.gui.control.tomoobjdisplaymode import DisplayMode
34
36
 
35
37
 
36
38
  class NXTomomillParamsAction(qt.QAction):
@@ -68,3 +70,55 @@ class CFGFileActiveLabel(qt.QLabel):
68
70
 
69
71
  def setInactive(self):
70
72
  self.setActive(active=False)
73
+
74
+
75
+ class TomoObjDisplayModeToolButton(qt.QToolButton):
76
+ """
77
+ Button to change the way tomo object are displayed.
78
+ Either using the full url or only a 'short' description.
79
+ """
80
+
81
+ sigDisplayModeChanged = qt.Signal(str)
82
+
83
+ _SHORT_DESC_TOOLTIP = "Use a short description of the tomo object. Two different scans can have the same short desciption"
84
+ _URL_TOOLTIP = (
85
+ "Use the full url to display the tomo object. Url is guaranted to be unique."
86
+ )
87
+
88
+ def __init__(self, parent=None) -> None:
89
+ super().__init__(parent)
90
+
91
+ self._shortDescIcon = tomwer_icons.getQIcon("short_description")
92
+ shortDescAction = qt.QAction(self._shortDescIcon, "short description", self)
93
+ shortDescAction.setToolTip(self._SHORT_DESC_TOOLTIP)
94
+
95
+ self._urlIcon = tomwer_icons.getQIcon("url")
96
+ urlDescAction = qt.QAction(self._urlIcon, "url", self)
97
+ urlDescAction.setToolTip(self._URL_TOOLTIP)
98
+
99
+ menu = qt.QMenu(self)
100
+ menu.addAction(shortDescAction)
101
+ menu.addAction(urlDescAction)
102
+ self.setMenu(menu)
103
+ self.setPopupMode(qt.QToolButton.InstantPopup)
104
+
105
+ # set up
106
+ self.setDisplayMode(DisplayMode.SHORT)
107
+
108
+ # connect signal / slot
109
+ shortDescAction.triggered.connect(
110
+ partial(self.setDisplayMode, DisplayMode.SHORT)
111
+ )
112
+ urlDescAction.triggered.connect(partial(self.setDisplayMode, DisplayMode.URL))
113
+
114
+ def setDisplayMode(self, mode: DisplayMode):
115
+ mode = DisplayMode.from_value(mode)
116
+ if mode is DisplayMode.SHORT:
117
+ self.setIcon(self._shortDescIcon)
118
+ self.setToolTip(self._SHORT_DESC_TOOLTIP)
119
+ elif mode is DisplayMode.URL:
120
+ self.setIcon(self._urlIcon)
121
+ self.setToolTip(self._URL_TOOLTIP)
122
+ else:
123
+ raise ValueError(f"display mode {mode} not handled")
124
+ self.sigDisplayModeChanged.emit(mode.value)
@@ -39,11 +39,11 @@ from silx.gui import qt
39
39
 
40
40
  from tomoscan.esrf.volume.utils import guess_volumes
41
41
  from tomoscan.identifier import BaseIdentifier
42
- from tomoscan.esrf.identifier.hdf5Identifier import HDF5TomoScanIdentifier
42
+ from tomoscan.esrf.identifier.hdf5Identifier import NXtomoScanIdentifier
43
43
 
44
44
  from tomwer.core.scan.blissscan import BlissScan
45
45
  from tomwer.core.scan.edfscan import EDFTomoScan
46
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
46
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
47
47
  from tomwer.core.scan.scanfactory import ScanFactory
48
48
  from tomwer.core.tomwer_object import TomwerObject
49
49
  from tomwer.core.volume.volumefactory import VolumeFactory
@@ -56,6 +56,8 @@ from tomwer.gui.utils.inputwidget import (
56
56
  NXTomomillOutputDirSelector,
57
57
  )
58
58
  from tomwer.gui.utils.qt_utils import block_signals
59
+ from tomwer.gui.control.tomoobjdisplaymode import DisplayMode
60
+ from tomwer.gui.control.actions import TomoObjDisplayModeToolButton
59
61
 
60
62
  logger = logging.getLogger(__name__)
61
63
 
@@ -240,6 +242,11 @@ class BlissHDF5DataListDialog(_DataListDialog):
240
242
  os.environ["TOMWER_DEFAULT_INPUT_DIR"]
241
243
  ):
242
244
  dialog.setDirectory(os.environ["TOMWER_DEFAULT_INPUT_DIR"])
245
+ elif dialog.directory() != os.getcwd() or str(dialog.directory()).startswith(
246
+ "/data"
247
+ ):
248
+ # if the directory as already been set by the user. Avoid redefining it
249
+ pass
243
250
  elif os.path.isdir("/data"):
244
251
  dialog.setDirectory("/data")
245
252
 
@@ -251,7 +258,8 @@ class BlissHDF5DataListDialog(_DataListDialog):
251
258
  added_scans = []
252
259
  for file_ in filesSelected:
253
260
  added_scans = self.add(file_)
254
- assert added_scans is not None
261
+ if added_scans is None:
262
+ continue
255
263
  added_scans.extend(added_scans)
256
264
  super()._callbackAddPath()
257
265
  self.datalist.setMySelection(added_scans)
@@ -331,6 +339,10 @@ class _RawDataListMainWindow(qt.QMainWindow):
331
339
  toolbar.addAction(self._parametersAction)
332
340
  self._parametersAction.triggered.connect(self._parametersTriggered)
333
341
 
342
+ # add tomo obj display mode
343
+ self._tomoObjdisplayAction = TomoObjDisplayModeToolButton(self)
344
+ toolbar.addWidget(self._tomoObjdisplayAction)
345
+
334
346
  # toolbar spacer
335
347
  spacer = qt.QWidget(toolbar)
336
348
  spacer.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Minimum)
@@ -351,8 +363,12 @@ class _RawDataListMainWindow(qt.QMainWindow):
351
363
 
352
364
  # connect signal / slot
353
365
  self._dialog.sigConfigFileChanged.connect(self._cfgFileChanged)
354
- self._dialog.sigOutputdirChanged.connect(self._propagateUpdateSignal)
355
- self._widget.sigUpdated.connect(self._propagateUpdateSignal)
366
+ self._dialog.sigOutputdirChanged.connect(self.sigUpdated)
367
+ self._widget.sigUpdated.connect(self.sigUpdated)
368
+ self._tomoObjdisplayAction.sigDisplayModeChanged.connect(self.setDisplayMode)
369
+
370
+ def setDisplayMode(self, *args, **kwargs):
371
+ self.datalist.setDisplayMode(*args, **kwargs)
356
372
 
357
373
  def getOutputFolder(self):
358
374
  return self._dialog.getOutputFolder()
@@ -360,9 +376,6 @@ class _RawDataListMainWindow(qt.QMainWindow):
360
376
  def setOutputFolder(self, output_dir):
361
377
  self._dialog.setOutputDialog(output_dir)
362
378
 
363
- def _propagateUpdateSignal(self):
364
- self.sigUpdated.emit()
365
-
366
379
  def _parametersTriggered(self):
367
380
  self._dialog.show()
368
381
  self._dialog.raise_()
@@ -516,6 +529,44 @@ class GenericScanListDialog(_DataListDialog):
516
529
  self.datalist.setMySelection(added_scans)
517
530
 
518
531
 
532
+ class GenericScanListWindow(qt.QMainWindow):
533
+ def __init__(self, parent=None) -> None:
534
+ super().__init__(parent)
535
+ self.setWindowFlags(qt.Qt.Widget)
536
+
537
+ self._widget = GenericScanListDialog()
538
+ self.datalist = self._widget.datalist
539
+ self.setCentralWidget(self._widget)
540
+
541
+ # toolbar
542
+ toolbar = qt.QToolBar()
543
+ toolbar.setMovable(False)
544
+ toolbar.setFloatable(False)
545
+ self.addToolBar(qt.Qt.TopToolBarArea, toolbar)
546
+
547
+ tomoObjdisplayAction = TomoObjDisplayModeToolButton(self)
548
+ toolbar.addWidget(tomoObjdisplayAction)
549
+
550
+ # set up
551
+ self.setDisplayMode(DisplayMode.SHORT)
552
+
553
+ # expose API
554
+ self.sigUpdated = self._widget.sigUpdated
555
+
556
+ # connect signal / slot
557
+ tomoObjdisplayAction.sigDisplayModeChanged.connect(self.setDisplayMode)
558
+
559
+ def setDisplayMode(self, display_mode: DisplayMode):
560
+ self.datalist.setDisplayMode(display_mode)
561
+
562
+ # expose API
563
+ def n_scan(self):
564
+ return self._widget.n_scan()
565
+
566
+ def add(self, *args, **kwargs):
567
+ self._widget.add(*args, **kwargs)
568
+
569
+
519
570
  class VolumeListDialog(_DataListDialog):
520
571
  """Dialog used to load EDFScan or HEDF5 scans"""
521
572
 
@@ -574,13 +625,19 @@ class _TomwerObjectList(qt.QTableWidget):
574
625
  self.menu.addAction(self._copyAction)
575
626
  self.menu.addAction(self._pasteAction)
576
627
 
628
+ self.setDisplayMode(DisplayMode.SHORT)
629
+
630
+ def setDisplayMode(self, mode: DisplayMode) -> None:
631
+ self._displayMode = DisplayMode.from_value(mode)
632
+ self._update()
633
+
577
634
  def n_data(self):
578
635
  return len(self._myitems)
579
636
 
580
637
  def remove_item(self, item):
581
638
  """Remove a given folder"""
582
639
  try:
583
- del self._myitems[item.text()]
640
+ del self._myitems[item.data(qt.Qt.UserRole).get_identifier().to_str()]
584
641
  except RuntimeError:
585
642
  # look like this could failed on some Qt or PyQt version (see issue 802)
586
643
  # no much that we can do so ignore it.
@@ -672,8 +729,8 @@ class _TomwerObjectList(qt.QTableWidget):
672
729
  raise TypeError(
673
730
  f"is expected to be an instance of str or of {TomwerObject} but {type(obj)}"
674
731
  )
675
- identifier_as_str = obj.get_identifier().to_str()
676
732
 
733
+ identifier_as_str = obj.get_identifier().to_str()
677
734
  if identifier_as_str in self._myitems:
678
735
  # in this case we will update the value. Because if the same identifier already exists at launch time
679
736
  # it will create two different objects that could be an issue.
@@ -694,14 +751,24 @@ class _TomwerObjectList(qt.QTableWidget):
694
751
  return (obj,)
695
752
 
696
753
  def getTextToDisplay(self, obj: TomwerObject):
697
- return obj.get_identifier().to_str()
754
+ if self._displayMode is DisplayMode.SHORT:
755
+ return obj.get_identifier().short_description()
756
+ elif self._displayMode is DisplayMode.URL:
757
+ return obj.get_identifier().to_str()
758
+ else:
759
+ raise ValueError(
760
+ f"Requested display mode {self._displayMode} is not handled"
761
+ )
698
762
 
699
763
  def setMySelection(self, datasets: tuple):
700
764
  if datasets is None:
701
765
  datasets = tuple()
702
766
  for row in range(self.rowCount()):
703
767
  item = self.item(row, 0)
704
- select_it = item.data(qt.Qt.UserRole) in datasets or item.text() in datasets
768
+ select_it = (
769
+ item.data(qt.Qt.UserRole).get_identifier().to_str() in datasets
770
+ or item.text() in datasets
771
+ )
705
772
  item.setSelected(select_it)
706
773
 
707
774
  def clear(self):
@@ -795,7 +862,7 @@ class _TomwerObjectList(qt.QTableWidget):
795
862
  class GenericScanList(_TomwerObjectList):
796
863
  """Data list able to manage directories (EDF/HDF5?) or files (HDF5)"""
797
864
 
798
- HEADER_NAMES = ("scan url",)
865
+ HEADER_NAMES = ("dataset",)
799
866
 
800
867
  def _getTomoObject(self, obj: str, allow_several: bool = False):
801
868
  """
@@ -869,7 +936,7 @@ class BlissScanList(_TomwerObjectList):
869
936
  types = qt.QMessageBox.Ok | qt.QMessageBox.Cancel
870
937
  msg.setStandardButtons(types)
871
938
 
872
- if HDF5TomoScan.is_nexus_nxtomo_file(data):
939
+ if NXtomoScan.is_nexus_nxtomo_file(data):
873
940
  text = (
874
941
  f"The input file `{data}` seems to contain `NXTomo` entries. "
875
942
  "and no valid `Bliss` valid entry. \n"
@@ -896,12 +963,12 @@ class BlissScanList(_TomwerObjectList):
896
963
  else:
897
964
  file_path = data
898
965
  else:
899
- identifier = HDF5TomoScanIdentifier.from_str(data)
966
+ identifier = NXtomoScanIdentifier.from_str(data)
900
967
  possible_entries.append(identifier.data_path)
901
968
  file_path = identifier.file_path
902
969
  created_scans = []
903
970
  for entry in possible_entries:
904
- scan = HDF5TomoScan(scan=file_path, entry=entry)
971
+ scan = NXtomoScan(scan=file_path, entry=entry)
905
972
  scan_objs = super().add(scan)
906
973
  if scan_objs is not None:
907
974
  for scan_obj in scan_objs:
@@ -125,10 +125,10 @@ class DataListenerWidget(qt.QMainWindow):
125
125
 
126
126
  # signal / slot connection
127
127
  self._actionGroup.triggered.connect(self._updateCentralWidget)
128
- self._controlWidget.sigActivated.connect(self._activated)
129
- self._controlWidget.sigDeactivated.connect(self._deactivated)
130
- self._configWindow.sigConfigurationChanged.connect(self._configChanged)
131
- self._configWindow.sigCFGFileChanged.connect(self._cfgFileChanged)
128
+ self._controlWidget.sigActivated.connect(self.sigActivate)
129
+ self._controlWidget.sigDeactivated.connect(self.sigDeactivate)
130
+ self._configWindow.sigConfigurationChanged.connect(self.sigConfigurationChanged)
131
+ self._configWindow.sigCFGFileChanged.connect(self.sigCFGFileChanged)
132
132
 
133
133
  # expose api
134
134
  self.activate = self._controlWidget.activate
@@ -171,18 +171,6 @@ class DataListenerWidget(qt.QMainWindow):
171
171
  self._listener().sigScanAdded.disconnect(self._acquisitionUpdated)
172
172
  self._listener().sigAcquisitionEnded.disconnect(self._acquisitionEnded)
173
173
 
174
- def _activated(self):
175
- self.sigActivate.emit()
176
-
177
- def _deactivated(self):
178
- self.sigDeactivate.emit()
179
-
180
- def _configChanged(self):
181
- self.sigConfigurationChanged.emit()
182
-
183
- def _cfgFileChanged(self, cfg_file):
184
- self.sigCFGFileChanged.emit(cfg_file)
185
-
186
174
  def _updateCentralWidget(self, action_triggered):
187
175
  action_to_widget = {
188
176
  self._controlAction: self._controlWidget,
@@ -99,10 +99,8 @@ class ControlWidget(qt.QWidget):
99
99
  """
100
100
  Ask the user the path to the folder to observe
101
101
  """
102
- defaultDirectory = self.getFolderObserved()
102
+ defaultDirectory = self._qteFolderSelected.text()
103
103
  if defaultDirectory is None or not os.path.isdir(defaultDirectory):
104
- if os.path.isdir(self.DEFAULT_DIRECTORY):
105
- defaultDirectory = self.DEFAULT_DIRECTORY
106
104
  if defaultDirectory is None:
107
105
  defaultDirectory = get_default_directory()
108
106
 
@@ -113,4 +111,4 @@ class ControlWidget(qt.QWidget):
113
111
  dialog.close()
114
112
  return
115
113
 
116
- self.setFolderObserved(dialog.selectedFiles()[0])
114
+ self._qteFolderSelected.setText(dialog.selectedFiles()[0])
@@ -148,7 +148,6 @@ class DataWatcherWidget(_DataWatcher, qt.QMainWindow):
148
148
 
149
149
  # set initial path to observe
150
150
  self.setFolderObserved(self._getInitPath())
151
- self._initStatusView()
152
151
 
153
152
  # hide all windows by default
154
153
  for widget in (
@@ -475,20 +474,10 @@ class DataWatcherWidget(_DataWatcher, qt.QMainWindow):
475
474
  self.observationThread.sigScanReady.disconnect(self._signalScanReady)
476
475
  self.obsThIsConnected = False
477
476
 
478
- def _initStatusView(self):
479
- """
480
- The status view need a thread to update the animated icon when scanning
481
- """
482
- self.__threadAnimation = QWaiterThread(0.1)
483
- self.__threadAnimation.finished.connect(self._updateAnimatedIcon)
484
-
485
477
  def _updateStatusView(self):
486
478
  """Update the processing state"""
487
479
  if self.currentStatus in self._animatedStates:
488
- if not self.__threadAnimation.isRunning():
489
- self.__threadAnimation.start()
490
- elif self.__threadAnimation is not None:
491
- self.__threadAnimation.wait(4000)
480
+ pass
492
481
  elif self.currentStatus == "acquisition ended":
493
482
  self._setStateIcon(silxicons.getQIcon("selected"))
494
483
  elif self.currentStatus == "failure":
@@ -506,18 +495,6 @@ class DataWatcherWidget(_DataWatcher, qt.QMainWindow):
506
495
  else:
507
496
  self._stateLabel.setPixmap(icon.pixmap(30, state=qt.QIcon.On))
508
497
 
509
- def _updateAnimatedIcon(self):
510
- """Simple function which manage the waiting icon"""
511
- if self.currentStatus in self._animatedStates:
512
- icon = self.animated_icon.currentIcon()
513
- if icon is None:
514
- icon = qt.QIcon()
515
- self.animated_icon._updateState()
516
- self._setStateIcon(icon)
517
-
518
- # get ready for the next animation
519
- self.__threadAnimation.start()
520
-
521
498
  def _signalScanReady(self, scan):
522
499
  if type(scan) is str:
523
500
  try:
@@ -1,7 +1,7 @@
1
1
  from typing import Optional
2
2
  from silx.gui import qt
3
3
  from tomwer.gui import icons as tomwericons
4
- from tomwer.core.utils import concatenate_dict
4
+ from tomwer.core.utils.dictutils import concatenate_dict
5
5
 
6
6
 
7
7
  class EmailComposition(qt.QWidget):
@@ -59,13 +59,10 @@ class EmailComposition(qt.QWidget):
59
59
  self.layout().addRow(self._textQLE)
60
60
 
61
61
  # connect signal / slot
62
- self._fromAddressesQLE.editingFinished.connect(self._changed)
63
- self._toAdressesQLE.editingFinished.connect(self._changed)
64
- self._subjectQLE.editingFinished.connect(self._changed)
65
- self._textQLE.textChanged.connect(self._changed)
66
-
67
- def _changed(self):
68
- self.sigChanged.emit()
62
+ self._fromAddressesQLE.editingFinished.connect(self.sigChanged)
63
+ self._toAdressesQLE.editingFinished.connect(self.sigChanged)
64
+ self._subjectQLE.editingFinished.connect(self.sigChanged)
65
+ self._textQLE.textChanged.connect(self.sigChanged)
69
66
 
70
67
  def getToAddrs(self) -> tuple:
71
68
  adresses = self._toAdressesQLE.text().replace(" ", "")
@@ -118,11 +115,8 @@ class EmailSettings(qt.QWidget):
118
115
  self.layout().addRow("port", self._portQLE)
119
116
 
120
117
  # connect signal / slot
121
- self._hostQLE.editingFinished.connect(self._changed)
122
- self._portQLE.editingFinished.connect(self._changed)
123
-
124
- def _changed(self):
125
- self.sigChanged.emit()
118
+ self._hostQLE.editingFinished.connect(self.sigChanged)
119
+ self._portQLE.editingFinished.connect(self.sigChanged)
126
120
 
127
121
  def getConfiguration(self) -> dict:
128
122
  return {"host": self._hostQLE.text(), "port": int(self._portQLE.text())}
@@ -166,11 +160,8 @@ class Emailwidget(qt.QTabWidget):
166
160
  )
167
161
 
168
162
  # connect signal / slot
169
- self._compositionWidget.sigChanged.connect(self._changed)
170
- self._serverSettingsWidget.sigChanged.connect(self._changed)
171
-
172
- def _changed(self):
173
- self.sigChanged.emit()
163
+ self._compositionWidget.sigChanged.connect(self.sigChanged)
164
+ self._serverSettingsWidget.sigChanged.connect(self.sigChanged)
174
165
 
175
166
  def getConfiguration(self) -> dict:
176
167
  return concatenate_dict(
@@ -32,7 +32,7 @@ from operator import itemgetter
32
32
 
33
33
  from silx.gui import qt
34
34
 
35
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
35
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
36
36
  from tomwer.core.scan.scanbase import TomwerScanBase
37
37
 
38
38
 
@@ -120,7 +120,7 @@ class _FoundScanModel(qt.QAbstractTableModel):
120
120
  return path.type
121
121
  elif isinstance(path, str) and path.startswith("hdf5 scan"):
122
122
  return "hdf5"
123
- elif HDF5TomoScan.directory_contains_scan(path) or "@" in path:
123
+ elif NXtomoScan.directory_contains_scan(path) or "@" in path:
124
124
  return "hdf5"
125
125
  else:
126
126
  return "edf"
@@ -35,7 +35,7 @@ from collections import OrderedDict
35
35
  from silx.gui import qt
36
36
 
37
37
  from tomwer.core.scan.blissscan import BlissScan
38
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
38
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
39
39
  from tomwer.core.scan.scanbase import TomwerScanBase
40
40
 
41
41
 
@@ -206,7 +206,7 @@ class _ObservedScanModel(qt.QAbstractTableModel):
206
206
  return obs.type
207
207
  elif isinstance(obs, BlissScan):
208
208
  return "hdf5"
209
- elif HDF5TomoScan.directory_contains_scan(directory=obs):
209
+ elif NXtomoScan.directory_contains_scan(directory=obs):
210
210
  return "hdf5"
211
211
  else:
212
212
  return "edf"
@@ -8,11 +8,11 @@ from silx.gui import qt
8
8
  from silx.gui.plot import Plot2D
9
9
  from silx.io.dictdump import h5todict
10
10
  from silx.io.url import DataUrl
11
+ from silx.io.utils import open as open_hdf5
11
12
  from silx.gui.dialog.DataFileDialog import DataFileDialog
12
13
 
13
14
  from tomoscan.esrf.scan.utils import cwd_context
14
- from tomoscan.framereducerbase import REDUCER_TARGET
15
- from tomoscan.io import HDF5File
15
+ from tomoscan.framereducer.target import REDUCER_TARGET
16
16
 
17
17
  from tomwer.io.utils import get_default_directory
18
18
 
@@ -249,7 +249,7 @@ class ReduceDarkFlatSelectorTableWidget(qt.QWidget):
249
249
  if not os.path.exists(file_path):
250
250
  _logger.error(f"file doesn't exists ({file_path})")
251
251
 
252
- with HDF5File(file_path, mode="r") as h5f:
252
+ with open_hdf5(file_path) as h5f:
253
253
  entries = tuple(h5f.keys())
254
254
 
255
255
  res = []
@@ -289,16 +289,16 @@ class ReduceDarkFlatSelectorTableWidget(qt.QWidget):
289
289
  for target in REDUCER_TARGET.values():
290
290
  if target in reduced_info_dict:
291
291
  reduced_frames = reduced_info_dict[target]
292
- reduced_frames[
293
- "reduce_frames_name"
294
- ] = f"{target} from {url.data_path()}@{os.path.basename(url.file_path())}"
292
+ reduced_frames["reduce_frames_name"] = (
293
+ f"{target} from {url.data_path()}@{os.path.basename(url.file_path())}"
294
+ )
295
295
  result.append(reduced_frames)
296
296
 
297
297
  if len(reduced_frames) == 0:
298
298
  # else we consider the data_path is the valid one
299
- reduced_frames[
300
- "reduce_frames_name"
301
- ] = f"{url.data_path()}@{os.path.basename(url.file_path())}"
299
+ reduced_frames["reduce_frames_name"] = (
300
+ f"{url.data_path()}@{os.path.basename(url.file_path())}"
301
+ )
302
302
  result.append(reduced_frames)
303
303
 
304
304
  return tuple(result)
@@ -3,11 +3,13 @@ import logging
3
3
  from silx.gui import qt
4
4
 
5
5
  from tomwer.gui.utils.qt_utils import block_signals
6
+ from tomwer.gui.control.actions import TomoObjDisplayModeToolButton
7
+ from tomwer.gui.control.tomoobjdisplaymode import DisplayMode
6
8
 
7
9
  _logger = logging.getLogger(__name__)
8
10
 
9
11
 
10
- class _SelectorWidget(qt.QWidget):
12
+ class _SelectorWidget(qt.QMainWindow):
11
13
  """widget used to select a dataset on a list (a scan or a volume for now)"""
12
14
 
13
15
  sigSelectionChanged = qt.Signal(list)
@@ -17,18 +19,38 @@ class _SelectorWidget(qt.QWidget):
17
19
  """signal emitted when the scan list change"""
18
20
 
19
21
  def __init__(self, parent=None):
20
- qt.QWidget.__init__(self, parent)
21
- self.setLayout(qt.QVBoxLayout())
22
+ qt.QMainWindow.__init__(self, parent)
23
+ # widget
24
+ self._mainWidget = qt.QWidget(self)
25
+ self._mainWidget.setLayout(qt.QVBoxLayout())
22
26
  self.dataList = self._buildDataList()
23
27
  self.dataList.setSelectionMode(qt.QAbstractItemView.ExtendedSelection)
24
- self.layout().addWidget(self.dataList)
25
- self.layout().addWidget(self._getAddAndRmButtons())
26
- self.layout().addWidget(self._getSendButtons())
28
+ self._mainWidget.layout().addWidget(self.dataList)
29
+ self._mainWidget.layout().addWidget(self._getAddAndRmButtons())
30
+ self._mainWidget.layout().addWidget(self._getSendButtons())
31
+ self._mainWidget.setAcceptDrops(True)
27
32
  self.setAcceptDrops(True)
33
+ self.setCentralWidget(self._mainWidget)
34
+
35
+ # toolbar
36
+ toolbar = qt.QToolBar()
37
+ toolbar.setMovable(False)
38
+ toolbar.setFloatable(False)
39
+ self.addToolBar(qt.Qt.TopToolBarArea, toolbar)
40
+
41
+ tomoObjdisplayAction = TomoObjDisplayModeToolButton(self)
42
+ toolbar.addWidget(tomoObjdisplayAction)
43
+
44
+ # set up
45
+ self.setDisplayMode(DisplayMode.SHORT)
28
46
 
29
47
  # connect signal / slot
30
48
  # for drag / drop we need to have an indirect call to the sigUpdated
31
49
  self.dataList.listChanged.connect(self._updatedFromDragDrop)
50
+ tomoObjdisplayAction.sigDisplayModeChanged.connect(self.setDisplayMode)
51
+
52
+ def setDisplayMode(self, *args, **kwargs):
53
+ self.dataList.setDisplayMode(*args, **kwargs)
32
54
 
33
55
  def _updatedFromDragDrop(self, *args, **kwargs):
34
56
  self.sigUpdated.emit()
@@ -99,7 +121,9 @@ class _SelectorWidget(qt.QWidget):
99
121
  def _selectActiveData(self):
100
122
  sItem = self.dataList.selectedItems()
101
123
  if sItem and len(sItem) >= 1:
102
- selection = [_item.text() for _item in sItem]
124
+ selection = [
125
+ _item.data(qt.Qt.UserRole).get_identifier().to_str() for _item in sItem
126
+ ]
103
127
  self.sigSelectionChanged.emit(list(selection))
104
128
  else:
105
129
  _logger.warning("No active scan detected")
@@ -112,7 +136,10 @@ class _SelectorWidget(qt.QWidget):
112
136
  def _callbackRemoveSelectedDatasets(self):
113
137
  """ """
114
138
  selected_items = self.dataList.selectedItems()
115
- tomwer_objs_to_remove = [item.data(qt.Qt.UserRole) for item in selected_items]
139
+ tomwer_objs_to_remove = [
140
+ item.data(qt.Qt.UserRole).get_identifier().to_str()
141
+ for item in selected_items
142
+ ]
116
143
  for tomwer_obj in tomwer_objs_to_remove:
117
144
  self.remove(tomwer_obj)
118
145
  self.sigUpdated.emit()
@@ -129,7 +156,7 @@ class _SelectorWidget(qt.QWidget):
129
156
 
130
157
  def removeSelectedDatasets(self):
131
158
  sItem = self.dataList.selectedItems()
132
- selection = [_item.text() for _item in sItem]
159
+ selection = [_item.text().get_identifier().to_str() for _item in sItem]
133
160
 
134
161
  with block_signals(self):
135
162
  # make sure sigUpdated is called only once.