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
@@ -37,11 +37,11 @@ from nxtomomill.utils import add_dark_flat_nx_file
37
37
  from silx.gui import qt
38
38
  from silx.gui.utils.testutils import TestCaseQt
39
39
  from silx.io.url import DataUrl
40
- from tomoscan.esrf.scan.hdf5scan import ImageKey
40
+ from nxtomo.nxobject.nxdetector import ImageKey
41
41
  from tomoscan.esrf.scan.utils import get_data
42
42
 
43
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
44
- from tomwer.core.utils.scanutils import MockHDF5
43
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
44
+ from tomwer.core.utils.scanutils import MockNXtomo
45
45
  from tomwer.gui.edit.dkrfpatch import DarkRefPatchWidget, _DarkOrFlatUrl
46
46
  from tomwer.tests.utils import skip_gui_test
47
47
 
@@ -62,13 +62,13 @@ class TestDarkOrFlatUrl(TestCaseQt):
62
62
  )
63
63
  self.output_folder = tempfile.mkdtemp()
64
64
  #
65
- hdf5_mock = MockHDF5(
65
+ hdf5_mock = MockNXtomo(
66
66
  scan_path=self.output_folder,
67
67
  n_ini_proj=20,
68
68
  n_proj=20,
69
69
  create_ini_dark=True,
70
- create_ini_ref=True,
71
- create_final_ref=True,
70
+ create_ini_flat=True,
71
+ create_final_flat=True,
72
72
  )
73
73
  self._scan = hdf5_mock.scan
74
74
  self.scan_url = DataUrl(
@@ -130,23 +130,23 @@ class TestDarkRefPatchWidget(TestCaseQt):
130
130
  self.output_folder1 = tempfile.mkdtemp()
131
131
  self.output_folder2 = tempfile.mkdtemp()
132
132
 
133
- hdf5_mock = MockHDF5(
133
+ hdf5_mock = MockNXtomo(
134
134
  scan_path=self.output_folder1,
135
135
  n_ini_proj=20,
136
136
  n_proj=20,
137
137
  create_ini_dark=True,
138
- create_ini_ref=True,
139
- create_final_ref=True,
138
+ create_ini_flat=True,
139
+ create_final_flat=True,
140
140
  )
141
141
  self._scanWithDarkAndRef = hdf5_mock.scan
142
142
 
143
- hdf5_mock = MockHDF5(
143
+ hdf5_mock = MockNXtomo(
144
144
  scan_path=self.output_folder2,
145
145
  n_ini_proj=20,
146
146
  n_proj=20,
147
147
  create_ini_dark=False,
148
- create_ini_ref=False,
149
- create_final_ref=False,
148
+ create_ini_flat=False,
149
+ create_final_flat=False,
150
150
  )
151
151
  self._scan = hdf5_mock.scan
152
152
  assert len(self._scan.darks) == 0
@@ -176,7 +176,7 @@ class TestDarkRefPatchWidget(TestCaseQt):
176
176
  self.assertTrue(self._widget.getEndDarkUrl() is None)
177
177
  self.assertTrue(self._widget.getEndFlatUrl() is None)
178
178
  self.process()
179
- new_scan = HDF5TomoScan(scan=self._scan.master_file, entry=self._scan.entry)
179
+ new_scan = NXtomoScan(scan=self._scan.master_file, entry=self._scan.entry)
180
180
  self.assertEqual(len(new_scan.darks), 1)
181
181
  self.assertTrue(0 in new_scan.darks)
182
182
  numpy.testing.assert_array_equal(
@@ -33,9 +33,9 @@ import tempfile
33
33
  import pytest
34
34
  from silx.gui import qt
35
35
  from silx.gui.utils.testutils import SignalListener, TestCaseQt
36
- from tomoscan.esrf.scan.hdf5scan import ImageKey
36
+ from nxtomo.nxobject.nxdetector import ImageKey
37
37
 
38
- from tomwer.core.utils.scanutils import MockHDF5
38
+ from tomwer.core.utils.scanutils import MockNXtomo
39
39
  from tomwer.gui.edit.imagekeyeditor import (
40
40
  ImageKeyDialog,
41
41
  ImageKeyUpgraderWidget,
@@ -55,7 +55,7 @@ class TestImageKeyEditorGUI(TestCaseQt):
55
55
  self._widget = ImageKeyDialog(parent=None)
56
56
  self.output_folder = tempfile.mkdtemp()
57
57
 
58
- hdf5_mock = MockHDF5(
58
+ hdf5_mock = MockNXtomo(
59
59
  scan_path=self.output_folder,
60
60
  n_ini_proj=20,
61
61
  n_proj=20,
@@ -2,21 +2,28 @@ import os
2
2
 
3
3
  import numpy
4
4
  import pytest
5
- from nxtomomill.nexus.nxtomo import NXtomo
6
5
  from silx.gui import qt
7
- from tomoscan.esrf.scan.hdf5scan import ImageKey
8
- from tomoscan.scanbase import _FOV
9
- from tomoscan.unitsystem.energysystem import EnergySI
10
- from tomoscan.unitsystem.metricsystem import MetricSystem
11
6
 
12
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
7
+ from pyunitsystem.energysystem import EnergySI
8
+ from pyunitsystem.metricsystem import MetricSystem
9
+
10
+ from nxtomo.application.nxtomo import NXtomo
11
+ from nxtomo.nxobject.nxdetector import ImageKey, FOV
12
+ from nxtomo.utils.transformation import (
13
+ build_matrix,
14
+ UDDetTransformation,
15
+ LRDetTransformation,
16
+ )
17
+ from nxtomo.nxobject.nxtransformations import NXtransformations
18
+
19
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
13
20
  from tomwer.gui.edit.nxtomoeditor import NXtomoEditor, _TranslationMetricEntry
14
21
  from tomwer.tests.conftest import qtapp # noqa F401
15
22
 
16
23
 
17
24
  @pytest.mark.parametrize("x_pixel_size", (None, 0.12))
18
25
  @pytest.mark.parametrize("y_pixel_size", (None, 0.0065))
19
- @pytest.mark.parametrize("field_of_view", _FOV.values())
26
+ @pytest.mark.parametrize("field_of_view", FOV.values())
20
27
  @pytest.mark.parametrize("distance", (None, 1.2))
21
28
  @pytest.mark.parametrize("energy", (None, 23.5))
22
29
  @pytest.mark.parametrize("x_flipped", (True, False))
@@ -42,14 +49,20 @@ def test_nx_editor(
42
49
  nx_tomo.instrument.detector.y_pixel_size = y_pixel_size
43
50
  nx_tomo.instrument.detector.field_of_view = field_of_view
44
51
  nx_tomo.instrument.detector.distance = distance
45
- nx_tomo.instrument.detector.x_flipped = x_flipped
46
- nx_tomo.instrument.detector.y_flipped = y_flipped
47
52
  nx_tomo.energy = energy
48
53
  nx_tomo.sample.x_translation = x_translation
49
54
  nx_tomo.sample.z_translation = z_translation
50
55
  nx_tomo.instrument.detector.image_key_control = [ImageKey.PROJECTION.value] * 12
51
56
  nx_tomo.instrument.detector.data = numpy.empty(shape=(12, 10, 10))
52
57
  nx_tomo.sample.rotation_angle = numpy.linspace(0, 20, num=12)
58
+ if x_flipped:
59
+ nx_tomo.instrument.detector.transformations.add_transformation(
60
+ LRDetTransformation()
61
+ )
62
+ if y_flipped:
63
+ nx_tomo.instrument.detector.transformations.add_transformation(
64
+ UDDetTransformation()
65
+ )
53
66
 
54
67
  file_path = os.path.join(tmp_path, "nxtomo.nx")
55
68
  entry = "entry0000"
@@ -58,7 +71,7 @@ def test_nx_editor(
58
71
  data_path=entry,
59
72
  )
60
73
 
61
- scan = HDF5TomoScan(file_path, entry)
74
+ scan = NXtomoScan(file_path, entry)
62
75
 
63
76
  # 2.0 create the widget and do the edition
64
77
  widget = NXtomoEditor()
@@ -107,7 +120,7 @@ def test_nx_editor(
107
120
  widget._xPixelSizeMetricEntry.setUnit("nm")
108
121
  widget._yPixelSizeMetricEntry.setValue(2.1e-7)
109
122
  widget._distanceMetricEntry.setValue("unknown")
110
- widget._fieldOfViewCB.setCurrentText(_FOV.HALF.value)
123
+ widget._fieldOfViewCB.setCurrentText(FOV.HALF.value)
111
124
  widget._xFlippedCB.setChecked(not x_flipped)
112
125
  widget._xTranslationQLE.setValue(1.8)
113
126
  widget._xTranslationQLE.setUnit("mm")
@@ -135,10 +148,21 @@ def test_nx_editor(
135
148
  assert overwrite_nx_tomo.instrument.detector.y_pixel_size.value == 2.1e-7
136
149
 
137
150
  assert overwrite_nx_tomo.instrument.detector.distance.value is None
138
- assert overwrite_nx_tomo.instrument.detector.field_of_view is _FOV.HALF
151
+ assert overwrite_nx_tomo.instrument.detector.field_of_view is FOV.HALF
139
152
 
140
- assert overwrite_nx_tomo.instrument.detector.x_flipped is not x_flipped
141
- assert overwrite_nx_tomo.instrument.detector.y_flipped is y_flipped
153
+ final_transformation = NXtransformations()
154
+
155
+ if y_flipped:
156
+ final_transformation.add_transformation(UDDetTransformation())
157
+ if not x_flipped: # as we invert _xFlippedCB combobox
158
+ final_transformation.add_transformation(LRDetTransformation())
159
+
160
+ numpy.testing.assert_allclose(
161
+ build_matrix(
162
+ overwrite_nx_tomo.instrument.detector.transformations.transformations
163
+ ),
164
+ build_matrix(final_transformation.transformations),
165
+ )
142
166
 
143
167
  numpy.testing.assert_array_almost_equal(
144
168
  overwrite_nx_tomo.sample.x_translation.value,
@@ -181,7 +205,7 @@ def test_nx_editor_lock(
181
205
  data_path=entry,
182
206
  )
183
207
 
184
- scan_1 = HDF5TomoScan(file_path, entry)
208
+ scan_1 = NXtomoScan(file_path, entry)
185
209
 
186
210
  nx_tomo_2 = NXtomo()
187
211
  nx_tomo_2.instrument.detector.x_pixel_size = 4.023
@@ -206,7 +230,7 @@ def test_nx_editor_lock(
206
230
  data_path=entry,
207
231
  )
208
232
 
209
- scan_2 = HDF5TomoScan(file_path, entry)
233
+ scan_2 = NXtomoScan(file_path, entry)
210
234
 
211
235
  # 2.0 create the widget and do the edition
212
236
  widget = NXtomoEditor()
File without changes
@@ -0,0 +1,80 @@
1
+ from silx.gui import qt
2
+ from typing import Optional
3
+
4
+
5
+ class CreateRawDataScreenshotsWidget(qt.QWidget):
6
+ """
7
+ Widget to allow the user define the screenshot to make of the raw data
8
+ """
9
+
10
+ sigConfigChanged = qt.Signal()
11
+ """emit when the configuration change"""
12
+
13
+ def __init__(self, parent=None):
14
+ super().__init__(parent)
15
+ self.setLayout(qt.QFormLayout())
16
+ # projections
17
+ self._projectionsCB = qt.QCheckBox("raw projections each", self)
18
+ self._projectionsSB = qt.QSpinBox(parent)
19
+ self._projectionsSB.setSuffix("°")
20
+ self.layout().addRow(self._projectionsCB, self._projectionsSB)
21
+ # flat field
22
+ self._flatFieldCB = qt.QCheckBox("first raw flat")
23
+ self.layout().addRow(self._flatFieldCB)
24
+ # dark field
25
+ self._darkFieldCB = qt.QCheckBox("first raw dark")
26
+ self.layout().addRow(self._darkFieldCB)
27
+
28
+ # set up
29
+ self._projectionsCB.setChecked(True)
30
+ self._flatFieldCB.setChecked(True)
31
+ self._darkFieldCB.setChecked(True)
32
+
33
+ # connect signal / slot
34
+ self._projectionsCB.toggled.connect(self._changed)
35
+ self._projectionsSB.valueChanged.connect(self._changed)
36
+ self._projectionsSB.setRange(0, 360)
37
+ self._projectionsSB.setValue(90)
38
+ self._flatFieldCB.toggled.connect(self._changed)
39
+ self._darkFieldCB.toggled.connect(self._changed)
40
+
41
+ def _changed(self, *args, **kwargs):
42
+ self.sigConfigChanged.emit()
43
+
44
+ def getConfiguration(self) -> dict:
45
+ return {
46
+ "raw_projections_required": self._projectionsCB.isChecked(),
47
+ "raw_projections_each": self._projectionsSB.value(),
48
+ "raw_darks_required": self._darkFieldCB.isChecked(),
49
+ "raw_flats_required": self._flatFieldCB.isChecked(),
50
+ }
51
+
52
+ def setRawProjections(self, required: bool, each_proj: Optional[int]):
53
+ self._projectionsCB.setChecked(required)
54
+ if each_proj is not None:
55
+ self._projectionsSB.setValue(int(each_proj))
56
+
57
+ def setFlatFieldRequired(self, required: bool):
58
+ self._flatFieldCB.setChecked(required)
59
+
60
+ def setDarkFieldRequired(self, required: bool):
61
+ self._darkFieldCB.setChecked(required)
62
+
63
+ def setConfiguration(self, configuration: dict):
64
+ assert isinstance(configuration, dict)
65
+ # handle raw projections
66
+ raw_projections_required = configuration.get(
67
+ "raw_projections_required", self._projectionsCB.isChecked()
68
+ )
69
+ raw_projections_each = configuration.get("raw_projections_each", None)
70
+ self.setRawProjections(
71
+ required=raw_projections_required, each_proj=raw_projections_each
72
+ )
73
+ # handle flat field
74
+ flat_field_required = configuration.get("raw_flats_required", None)
75
+ if flat_field_required is not None:
76
+ self.setFlatFieldRequired(flat_field_required)
77
+ # handle flat field
78
+ dark_field_required = configuration.get("raw_darks_required", None)
79
+ if dark_field_required is not None:
80
+ self.setDarkFieldRequired(dark_field_required)
@@ -0,0 +1,214 @@
1
+ import os
2
+ from silx.gui import qt
3
+ from silx.utils.enum import Enum as _Enum
4
+ from tomwer.core.process.icat.gallery import OutputFormat
5
+ from tomwer.gui.qlefilesystem import QLFileSystem
6
+ from tomwer.io.utils import get_default_directory
7
+ from tomwer.core.utils.dictutils import concatenate_dict
8
+ from tomwer.core.process.icat.gallery import Binning
9
+
10
+ from .publish import PublishProcessedDataWidget
11
+
12
+
13
+ class _GalleryOutputDir(qt.QGroupBox):
14
+ class OutputDirMode(_Enum):
15
+ DATASET_GALLERY = "dataset gallery"
16
+ PROPOSAL_GALLERY = "proposal GALLERY"
17
+ CUSTOM = "custom"
18
+
19
+ def __init__(self, parent=None):
20
+ super().__init__(parent)
21
+ self.setLayout(qt.QGridLayout())
22
+ # dataset gallery option
23
+ self._datasetGalleryQRB = qt.QRadioButton(
24
+ self.OutputDirMode.DATASET_GALLERY.value, self
25
+ )
26
+ self.layout().addWidget(self._datasetGalleryQRB, 0, 0, 1, 4)
27
+ # proposal gallery option
28
+ self._proposalGalleryQRB = qt.QRadioButton(
29
+ self.OutputDirMode.PROPOSAL_GALLERY.value, self
30
+ )
31
+ self.layout().addWidget(self._proposalGalleryQRB, 1, 0, 1, 4)
32
+
33
+ # other option
34
+ self._otherQRB = qt.QRadioButton(self.OutputDirMode.CUSTOM.value, self)
35
+ self._otherQRB.setCheckable(True)
36
+ self.layout().addWidget(self._otherQRB, 2, 0, 1, 4)
37
+
38
+ self._otherQLE = QLFileSystem(
39
+ "", self, filters=qt.QDir.NoDotAndDotDot | qt.QDir.Dirs
40
+ )
41
+ self.layout().addWidget(self._otherQLE, 3, 1, 1, 2)
42
+ style = qt.QApplication.style()
43
+ icon_opendir = style.standardIcon(qt.QStyle.SP_DirOpenIcon)
44
+ self._selectOtherQLE = qt.QPushButton(icon_opendir, "", self)
45
+ self._selectOtherQLE.setIcon(icon_opendir)
46
+ self.layout().addWidget(self._selectOtherQLE, 3, 3, 1, 1)
47
+
48
+ # button group
49
+ self._buttonGroup = qt.QButtonGroup()
50
+ self._buttonGroup.setExclusive(True)
51
+ self._buttonGroup.addButton(self._datasetGalleryQRB)
52
+ self._buttonGroup.addButton(self._proposalGalleryQRB)
53
+ self._buttonGroup.addButton(self._otherQRB)
54
+
55
+ # vertical spacer
56
+ self._vSpacer = qt.QWidget(self)
57
+ self._vSpacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
58
+ self.layout().addWidget(self._vSpacer, 99, 0, 1, 1)
59
+
60
+ # set up GUI
61
+ self._datasetGalleryQRB.setChecked(True)
62
+ self._modeChanged()
63
+
64
+ # connect signal / slot
65
+ self._buttonGroup.buttonClicked.connect(self._modeChanged)
66
+ self._selectOtherQLE.released.connect(self._selectOutput)
67
+
68
+ def _selectOutput(self): # pragma: no cover
69
+ defaultDirectory = self._selectOtherQLE.text()
70
+ if not os.path.isdir(defaultDirectory):
71
+ defaultDirectory = get_default_directory()
72
+
73
+ dialog = qt.QFileDialog(self, directory=defaultDirectory)
74
+ dialog.setFileMode(qt.QFileDialog.DirectoryOnly)
75
+
76
+ if not dialog.exec_():
77
+ dialog.close()
78
+ return
79
+
80
+ self._selectOtherQLE.setText(dialog.selectedFiles()[0])
81
+
82
+ def getOutputFolderMode(self):
83
+ if self._datasetGalleryQRB.isChecked():
84
+ return _GalleryOutputDir.OutputDirMode.DATASET_GALLERY
85
+ elif self._proposalGalleryQRB.isChecked():
86
+ return _GalleryOutputDir.OutputDirMode.PROPOSAL_GALLERY
87
+ elif self._otherQRB.isChecked():
88
+ return _GalleryOutputDir.OutputDirMode.CUSTOM
89
+ else:
90
+ raise NotImplementedError
91
+
92
+ def setOutputFolderMode(self, mode):
93
+ mode = _GalleryOutputDir.OutputDirMode.from_value(mode)
94
+ if mode is _GalleryOutputDir.OutputDirMode.PROPOSAL_GALLERY:
95
+ self._proposalGalleryQRB.setChecked(True)
96
+ elif mode is _GalleryOutputDir.OutputDirMode.DATASET_GALLERY:
97
+ self._datasetGalleryQRB.setChecked(True)
98
+ elif mode is _GalleryOutputDir.OutputDirMode.CUSTOM:
99
+ self._otherQRB.setChecked(True)
100
+ else:
101
+ raise NotImplementedError
102
+ self._modeChanged()
103
+
104
+ def getOtherOutputDir(self):
105
+ return self._otherQLE.text()
106
+
107
+ def setOtherOutputDir(self, path: str):
108
+ self._otherQLE.setText(path)
109
+
110
+ def _modeChanged(self, *args, **kwargs):
111
+ custom_active = self._otherQRB.isChecked()
112
+ self._otherQLE.setEnabled(custom_active)
113
+ self._selectOtherQLE.setEnabled(custom_active)
114
+
115
+
116
+ class GalleryWidget(qt.QWidget):
117
+ """Widget to let the user define the output location of the screenshots"""
118
+
119
+ sigConfigChanged = qt.Signal()
120
+ """emit when the configuration has changed"""
121
+
122
+ def __init__(self, parent=None):
123
+ super().__init__(parent)
124
+ self.setLayout(qt.QFormLayout())
125
+
126
+ # screenshot precision
127
+ self._precisonQCB = qt.QComboBox(self)
128
+ self._precisonQCB.addItem("uint8")
129
+ self.layout().addRow("precision", self._precisonQCB)
130
+ # binning
131
+ self._binningQCB = qt.QComboBox(self)
132
+ self._binningQCB.addItems(Binning.values())
133
+ self.layout().addRow("binning", self._binningQCB)
134
+ self._binningQCB.setCurrentText(Binning.SIXTEEN_BY_SIXTEEN.value)
135
+ self._binningQCB.setToolTip(
136
+ "To speed up display of the gallery at the data portal side it is highly recommended to bin screenshots"
137
+ ) # recommanded size: 5ko for the entire gallery
138
+ # output format
139
+ self._outputFormat = qt.QComboBox(self)
140
+ self._outputFormat.addItems(OutputFormat.values())
141
+ self.layout().addRow("outoutput_location_modeput format", self._outputFormat)
142
+ # gallery output dir
143
+ self._outputDirWidget = _GalleryOutputDir(self)
144
+ self._outputLocationLabel = qt.QLabel("output location", self)
145
+ self.layout().addRow(self._outputLocationLabel, self._outputDirWidget)
146
+ self._outputDirWidget.hide()
147
+ self._outputLocationLabel.hide()
148
+ # overwrite
149
+ self._overwriteCB = qt.QCheckBox("overwrite", self)
150
+ self._overwriteCB.setChecked(True)
151
+ self.layout().addRow(self._overwriteCB)
152
+ # publishing setting
153
+ self._publishConfig = PublishProcessedDataWidget(self)
154
+ self._publisherGB = qt.QGroupBox("icat info")
155
+ self._publisherGB.setLayout(qt.QVBoxLayout())
156
+ self._publisherGB.layout().addWidget(self._publishConfig)
157
+ self.layout().addRow(self._publisherGB)
158
+ # connect signal / slot
159
+ self._outputFormat.currentIndexChanged.connect(self._configChanged)
160
+ self._overwriteCB.toggled.connect(self._configChanged)
161
+ self._publishConfig.sigConfigChanged.connect(self.sigConfigChanged)
162
+ self._binningQCB.currentIndexChanged.connect(self._configChanged)
163
+
164
+ def getOutputFormat(self) -> OutputFormat:
165
+ return OutputFormat.from_value(self._outputFormat.currentText())
166
+
167
+ def setOutputFormat(self, format: OutputFormat):
168
+ format = OutputFormat.from_value(format)
169
+ self._outputFormat.setCurrentText(format.value)
170
+
171
+ def getBinning(self) -> Binning:
172
+ return Binning.from_value(self._binningQCB.currentText())
173
+
174
+ def setBinning(self, binning: Binning):
175
+ binning = Binning.from_value(binning)
176
+ self._binningQCB.setCurrentText(binning.value)
177
+
178
+ def getConfiguration(self):
179
+ return concatenate_dict(
180
+ self._publishConfig.getConfiguration(),
181
+ {
182
+ "output_format": self.getOutputFormat().value,
183
+ "output_location_mode": self._outputDirWidget.getOutputFolderMode().value,
184
+ "custom_output": self._outputDirWidget.getOtherOutputDir(),
185
+ "overwrite": self._overwriteCB.isChecked(),
186
+ "binning": self.getBinning().value,
187
+ },
188
+ )
189
+
190
+ def setConfiguration(self, config: dict):
191
+ self._publishConfig.setConfiguration(config)
192
+ output_format = config.get("output_format", None)
193
+ if output_format is not None:
194
+ self.setOutputFormat(output_format)
195
+
196
+ output_location_mode = config.get("output_location_mode", None)
197
+ if output_location_mode is not None:
198
+ self._outputDirWidget.setOutputFolderMode(output_location_mode)
199
+
200
+ custom_output = config.get("custom_output", None)
201
+ if custom_output is not None:
202
+ self._outputDirWidget.setOtherOutputDir(custom_output)
203
+
204
+ overwrite = config.get("overwrite", None)
205
+ if overwrite is not None:
206
+ overwrite = overwrite in (True, "True", 1)
207
+ self._overwriteCB.setChecked(overwrite)
208
+
209
+ binning = config.get("binning", None)
210
+ if binning is not None:
211
+ self.setBinning(binning=binning)
212
+
213
+ def _configChanged(self, *args, **kwargs):
214
+ self.sigConfigChanged.emit()
@@ -0,0 +1,187 @@
1
+ import platform
2
+ from silx.gui import qt
3
+ from tomwer.core.scan.scanbase import TomwerScanBase
4
+ from tomwer.gui.utils.qt_utils import block_signals
5
+ from tomwer.gui.utils.buttons import PadlockButton
6
+
7
+
8
+ class PublishProcessedDataWidget(qt.QWidget):
9
+ sigConfigChanged = qt.Signal()
10
+ """emit when the configuration changed"""
11
+
12
+ KNOW_BEAMLINES = sorted(
13
+ ("bm05", "bm18", "id11", "id15a", "id16a", "id16b", "id17", "id19")
14
+ )
15
+
16
+ _TOOLTIP_PAD_LOCKS = "when receive a new scan the value will be updated if valid informations are found. If the field is lock then no update will be done automatically."
17
+
18
+ def __init__(self, parent=None) -> None:
19
+ super().__init__(parent)
20
+ self.setLayout(qt.QGridLayout())
21
+
22
+ # beamline
23
+ self._beamlineCB = qt.QComboBox(self)
24
+ self._beamlineCB.setEditable(True)
25
+ self._beamlineCB.addItems(self.KNOW_BEAMLINES)
26
+ self._beamlineCB.lineEdit().setPlaceholderText("beamline name")
27
+ self.layout().addWidget(
28
+ qt.QLabel("beamline", self),
29
+ 0,
30
+ 0,
31
+ 1,
32
+ 1,
33
+ )
34
+ self.layout().addWidget(
35
+ self._beamlineCB,
36
+ 0,
37
+ 1,
38
+ 1,
39
+ 1,
40
+ )
41
+ self._beamlinePLB = PadlockButton(self)
42
+ self._beamlinePLB.setToolTip(self._TOOLTIP_PAD_LOCKS)
43
+ self.layout().addWidget(
44
+ self._beamlinePLB,
45
+ 0,
46
+ 2,
47
+ 1,
48
+ 1,
49
+ )
50
+
51
+ # proposal
52
+ self._proposalQLE = qt.QLineEdit("", self)
53
+ self._proposalQLE.setPlaceholderText("proposal name")
54
+ self.layout().addWidget(
55
+ qt.QLabel("proposal", self),
56
+ 1,
57
+ 0,
58
+ 1,
59
+ 1,
60
+ )
61
+ self.layout().addWidget(
62
+ self._proposalQLE,
63
+ 1,
64
+ 1,
65
+ 1,
66
+ 1,
67
+ )
68
+ self._proposalPLB = PadlockButton(self)
69
+ self._proposalPLB.setToolTip(self._TOOLTIP_PAD_LOCKS)
70
+ self.layout().addWidget(
71
+ self._proposalPLB,
72
+ 1,
73
+ 2,
74
+ 1,
75
+ 1,
76
+ )
77
+
78
+ # dataset
79
+ self._datasetQLE = qt.QLineEdit("", self)
80
+ self._datasetQLE.setPlaceholderText("dataset name")
81
+ self.layout().addWidget(
82
+ qt.QLabel("dataset", self),
83
+ 2,
84
+ 0,
85
+ 1,
86
+ 1,
87
+ )
88
+ self.layout().addWidget(
89
+ self._datasetQLE,
90
+ 2,
91
+ 1,
92
+ 1,
93
+ 1,
94
+ )
95
+ self._datasetPLB = PadlockButton(self)
96
+ self._datasetPLB.setToolTip(self._TOOLTIP_PAD_LOCKS)
97
+ self.layout().addWidget(
98
+ self._datasetPLB,
99
+ 2,
100
+ 2,
101
+ 1,
102
+ 1,
103
+ )
104
+
105
+ # set up
106
+ default_beamline = self.getDefaultBeamline()
107
+ if default_beamline is not None:
108
+ self._beamlineCB.setCurrentText(default_beamline)
109
+
110
+ # connect signal / slot
111
+ self._beamlinePLB.toggled.connect(self._configChanged)
112
+ self._proposalPLB.toggled.connect(self._configChanged)
113
+ self._datasetPLB.toggled.connect(self._configChanged)
114
+ self._beamlineCB.currentTextChanged.connect(self._configChanged)
115
+ self._proposalQLE.textEdited.connect(self._configChanged)
116
+ self._datasetQLE.textEdited.connect(self._configChanged)
117
+
118
+ @staticmethod
119
+ def getDefaultBeamline():
120
+ hostname = platform.node()
121
+ for beamline in PublishProcessedDataWidget.KNOW_BEAMLINES:
122
+ if beamline in hostname:
123
+ return beamline
124
+
125
+ return None
126
+
127
+ def set_auto_update(self, update: bool):
128
+ self._beamlinePLB.setChecked(not update)
129
+ self._proposalPLB.setChecked(not update)
130
+ self._datasetPLB.setChecked(not update)
131
+
132
+ def _configChanged(self, *args, **kwargs):
133
+ self.sigConfigChanged.emit()
134
+
135
+ def getConfiguration(self) -> dict:
136
+ return {
137
+ "beamline_auto_update": not self._beamlinePLB.isChecked(),
138
+ "dataset_auto_update": not self._datasetPLB.isChecked(),
139
+ "proposal_auto_update": not self._proposalPLB.isChecked(),
140
+ "beamline": self._beamlineCB.currentText(),
141
+ "dataset": self._datasetQLE.text(),
142
+ "proposal": self._proposalQLE.text(),
143
+ }
144
+
145
+ def setConfiguration(self, configuration: dict):
146
+ with block_signals(self):
147
+ # handle beamline
148
+ beamline = configuration.get("beamline", None)
149
+ if beamline is not None:
150
+ self._beamlineCB.setCurrentText(beamline)
151
+ beamline_auto_update = configuration.get("beamline_auto_update", None)
152
+ if beamline_auto_update is not None:
153
+ self._beamlinePLB.setChecked(not beamline_auto_update)
154
+
155
+ # handle dataset
156
+ dataset = configuration.get("dataset", None)
157
+ if dataset is not None:
158
+ self._datasetQLE.setText(dataset)
159
+ dataset_auto_update = configuration.get("dataset_auto_update", None)
160
+ if dataset_auto_update is not None:
161
+ self._datasetPLB.setChecked(not dataset_auto_update)
162
+
163
+ # handle proposal
164
+ proposal = configuration.get("proposal", None)
165
+ if proposal is not None:
166
+ self._proposalQLE.setText(proposal)
167
+ proposal_auto_update = configuration.get("proposal_auto_update", None)
168
+ if proposal_auto_update is not None:
169
+ self._proposalPLB.setChecked(not proposal_auto_update)
170
+
171
+ self._configChanged()
172
+
173
+ def setScan(self, scan: TomwerScanBase):
174
+ if not isinstance(scan, TomwerScanBase):
175
+ raise TypeError(
176
+ f"scan is expected to be an instance of {TomwerScanBase}, {type(scan)} provided instead"
177
+ )
178
+
179
+ new_config = {}
180
+ if not self._proposalPLB.isChecked():
181
+ new_config["proposal"] = scan.get_proposal_name()
182
+ if not self._beamlinePLB.isChecked():
183
+ new_config["beamline"] = scan.instrument_name
184
+ if not self._datasetPLB.isChecked():
185
+ new_config["dataset"] = scan.sample_name
186
+
187
+ self.setConfiguration(new_config)