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
@@ -28,13 +28,23 @@ __license__ = "MIT"
28
28
  __date__ = "11/10/2021"
29
29
 
30
30
 
31
+ import logging
31
32
  from typing import Optional
33
+ from functools import lru_cache as cache
32
34
 
33
35
  from silx.gui import qt
34
- from sluurp.utils import get_partitions
36
+ from sluurp.utils import get_partitions, get_partition_gpus
35
37
 
36
38
  from tomwer.core.settings import SlurmSettings, SlurmSettingsMode
37
39
  from tomwer.gui.utils.qt_utils import block_signals
40
+ from tomwer.gui.configuration.action import (
41
+ BasicConfigurationAction,
42
+ ExpertConfigurationAction,
43
+ )
44
+ from tomwer.gui.configuration.level import ConfigurationLevel
45
+ from nxtomomill.io.utils import convert_str_to_tuple
46
+
47
+ _logger = logging.getLogger(__name__)
38
48
 
39
49
 
40
50
  class SlurmSettingsDialog(qt.QDialog):
@@ -58,10 +68,7 @@ class SlurmSettingsDialog(qt.QDialog):
58
68
  self._buttons.button(qt.QDialogButtonBox.Close).clicked.connect(self.close)
59
69
 
60
70
  # connect signal /slot
61
- self._mainWidget.sigConfigChanged.connect(self._configChanged)
62
-
63
- def _configChanged(self, *args, **kwargs):
64
- self.sigConfigChanged.emit()
71
+ self._mainWidget.sigConfigChanged.connect(self.sigConfigChanged)
65
72
 
66
73
  def isSlurmActive(self):
67
74
  return self._mainWidget.isSlurmActive()
@@ -84,6 +91,29 @@ class SlurmSettingsWindow(qt.QMainWindow):
84
91
 
85
92
  def __init__(self, parent: Optional[qt.QWidget] = None) -> None:
86
93
  super().__init__(parent)
94
+
95
+ # define toolbar
96
+ toolbar = qt.QToolBar(self)
97
+ self.addToolBar(qt.Qt.TopToolBarArea, toolbar)
98
+
99
+ self.__configurationModesAction = qt.QAction(self)
100
+ self.__configurationModesAction.setCheckable(False)
101
+ menu = qt.QMenu(self)
102
+ self.__configurationModesAction.setMenu(menu)
103
+ toolbar.addAction(self.__configurationModesAction)
104
+
105
+ self.__configurationModesGroup = qt.QActionGroup(self)
106
+ self.__configurationModesGroup.setExclusive(True)
107
+ self.__configurationModesGroup.triggered.connect(self._userModeChanged)
108
+
109
+ self._basicConfigAction = BasicConfigurationAction(toolbar)
110
+ menu.addAction(self._basicConfigAction)
111
+ self.__configurationModesGroup.addAction(self._basicConfigAction)
112
+ self._expertConfiguration = ExpertConfigurationAction(toolbar)
113
+ menu.addAction(self._expertConfiguration)
114
+ self.__configurationModesGroup.addAction(self._expertConfiguration)
115
+
116
+ # define maini widget
87
117
  self._mainWidget = qt.QWidget(self)
88
118
  self._mainWidget.setLayout(qt.QFormLayout())
89
119
 
@@ -92,13 +122,15 @@ class SlurmSettingsWindow(qt.QMainWindow):
92
122
  self._modeCombox.addItems(SlurmSettingsMode.values())
93
123
  self._modeCombox.setCurrentText(SlurmSettingsMode.GENERIC.value)
94
124
 
95
- self._settingsWidget = SlurmSettingsWidget(self)
125
+ self._settingsWidget = SlurmSettingsWidget(self, jobLimitation=None)
96
126
  self._mainWidget.layout().addRow(self._settingsWidget)
97
127
 
98
128
  self.setCentralWidget(self._mainWidget)
99
129
 
100
130
  # set up
101
131
  self._reloadPredefinedSettings()
132
+ self._basicConfigAction.setChecked(True)
133
+ self._userModeChanged(self._basicConfigAction)
102
134
 
103
135
  # connect signal / slot
104
136
  self._modeCombox.currentIndexChanged.connect(self._reloadPredefinedSettings)
@@ -106,6 +138,17 @@ class SlurmSettingsWindow(qt.QMainWindow):
106
138
  # when the settings widget is edited them we automatically move to 'manual' settings. To notify visually the user
107
139
  self._settingsWidget.sigConfigChanged.connect(self._switchToManual)
108
140
 
141
+ def _userModeChanged(self, action):
142
+ self.__configurationModesAction.setIcon(action.icon())
143
+ self.__configurationModesAction.setToolTip(action.tooltip())
144
+ if action is self._basicConfigAction:
145
+ level = ConfigurationLevel.OPTIONAL
146
+ elif action is self._expertConfiguration:
147
+ level = ConfigurationLevel.ADVANCED
148
+ else:
149
+ raise NotImplementedError
150
+ self._settingsWidget.setConfigurationLevel(level)
151
+
109
152
  def _reloadPredefinedSettings(self, *args, **kkwargs):
110
153
  """
111
154
  reload settings from some predefined configuration
@@ -125,6 +168,7 @@ class SlurmSettingsWindow(qt.QMainWindow):
125
168
  "job_name": settingsClass.PROJECT_NAME,
126
169
  "walltime": settingsClass.DEFAULT_WALLTIME,
127
170
  "python_venv": settingsClass.PYTHON_VENV,
171
+ "modules": settingsClass.MODULES_TO_LOAD,
128
172
  }
129
173
  )
130
174
 
@@ -179,13 +223,17 @@ class SlurmSettingsWidget(qt.QWidget):
179
223
  self._queue = qt.QComboBox(self)
180
224
  self._queue.setEditable(True)
181
225
  for partition in get_partitions():
226
+ if partition in ("nice*",):
227
+ # filter some node that we cannot access in fact
228
+ continue
182
229
  self._queue.addItem(partition)
183
230
  self.layout().addRow("queue / partition", self._queue)
184
231
 
185
232
  # n workers
186
233
  self._nWorkers = qt.QSpinBox(self)
187
234
  self._nWorkers.setRange(1, 100)
188
- self.layout().addRow("number of task", self._nWorkers)
235
+ self._nWorkersLabel = qt.QLabel("number of task", self)
236
+ self.layout().addRow(self._nWorkersLabel, self._nWorkers)
189
237
 
190
238
  # ncores active
191
239
  self._nCores = qt.QSpinBox(self)
@@ -218,17 +266,34 @@ class SlurmSettingsWidget(qt.QWidget):
218
266
  self._wallTimeLabel = qt.QLabel("wall time", self)
219
267
  self.layout().addRow(self._wallTimeLabel, self._wallTimeQLE)
220
268
 
221
- # python exe
222
- self._pythonVenv = qt.QLineEdit("", self)
223
- self.layout().addRow(
224
- "source script before processing (python venv)", self._pythonVenv
225
- )
269
+ # python exe / modules
270
+ self._preProcessingGroup = qt.QGroupBox("pre-processing", self)
271
+ self._preProcessingGroup.setLayout(qt.QFormLayout())
272
+ self._preProcessingButtonGroup = qt.QButtonGroup(self)
273
+ self._preProcessingButtonGroup.setExclusive(True)
274
+ self.layout().addRow(self._preProcessingGroup)
275
+
276
+ # python venv
277
+ self._pythonVenv = qt.QLineEdit("/scisoft/tomotools/activate stable", self)
278
+ self._sourceScriptCB = qt.QRadioButton("source script (python venv)", self)
279
+ self._preProcessingButtonGroup.addButton(self._sourceScriptCB)
280
+ self._preProcessingGroup.layout().addRow(self._sourceScriptCB, self._pythonVenv)
226
281
  self._pythonVenv.setToolTip(
227
282
  """
228
283
  Optional path to a bash script to source before executing the script.
229
284
  """
230
285
  )
231
286
 
287
+ self._modulesQLE = qt.QLineEdit(", ".join(SlurmSettings.MODULES_TO_LOAD), self)
288
+ self._modulesCB = qt.QRadioButton("module(s) to load", self)
289
+ self._preProcessingButtonGroup.addButton(self._modulesCB)
290
+ self._preProcessingGroup.layout().addRow(self._modulesCB, self._modulesQLE)
291
+ self._preProcessingGroup.setToolTip(
292
+ """
293
+ Optional list of modules to load before executing the script. each module must be separated by a coma
294
+ """
295
+ )
296
+
232
297
  # job name
233
298
  self._jobName = qt.QLineEdit("", self)
234
299
  self._jobName.setToolTip(
@@ -257,6 +322,39 @@ class SlurmSettingsWidget(qt.QWidget):
257
322
  self._dashboardPortLabel = qt.QLabel("dashboard port", self)
258
323
  self.layout().addRow(self._dashboardPortLabel, self._dashboardPort)
259
324
 
325
+ # sbatch advance parameters
326
+ self._sbatchAdvancedParameters = qt.QGroupBox("sbatch advanced settings", self)
327
+ self._sbatchAdvancedParameters.setLayout(qt.QFormLayout())
328
+ self.layout().addRow(self._sbatchAdvancedParameters)
329
+
330
+ ## export parameter
331
+ self._exportValueCM = qt.QComboBox(self)
332
+ self._exportValueCM.addItems(("NONE", "ALL"))
333
+ self._exportValueCM.setItemData(
334
+ self._exportValueCM.findText("NONE"),
335
+ """
336
+ Only SLURM_* variables from the user environment will be defined. User must use absolute path to the binary to be executed that will define the environment. User can not specify explicit environment variables with "NONE". However, Slurm will then implicitly attempt to load the user's environment on the node where the script is being executed, as if --get-user-env was specified. \nThis option is particularly important for jobs that are submitted on one cluster and execute on a different cluster (e.g. with different paths). To avoid steps inheriting environment export settings (e.g. "NONE") from sbatch command, the environment variable SLURM_EXPORT_ENV should be set to "ALL" in the job script.
337
+ """,
338
+ )
339
+ self._exportValueCM.setItemData(
340
+ self._exportValueCM.findText("ALL"),
341
+ """
342
+ All of the user's environment will be loaded (either from the caller's environment or from a clean environment if --get-user-env is specified). \nCan fail when submitting cross-platform jobs and user has some module loaded
343
+ """,
344
+ )
345
+ self._exportValueCM.setCurrentText("NONE")
346
+ self._sbatchAdvancedParameters.layout().addRow("--export", self._exportValueCM)
347
+
348
+ ## gpu card
349
+ self._gpuCardCB = qt.QComboBox(self)
350
+ self._gpuCardCB.setToolTip(
351
+ "Specify a GPU card to be used. Using the -C command from sbatch"
352
+ )
353
+ self._gpuCardCB.setEditable(
354
+ True
355
+ ) # let the user the ability to provide a GPU that is not found for now (expecting he knows what he is doing)
356
+ self._sbatchAdvancedParameters.layout().addRow("-C (gpu card)", self._gpuCardCB)
357
+
260
358
  # simplify gui
261
359
  self._wallTimeLabel.hide()
262
360
  self._wallTimeQLE.hide()
@@ -266,16 +364,23 @@ class SlurmSettingsWidget(qt.QWidget):
266
364
  self._job_nameQLabel.hide()
267
365
  self._portLabel.hide() # for now we don't use the port. This can be done automatically
268
366
  self._port.hide() # for now we don't use the port. This can be done automatically
367
+ # for now nworker == ntask is not used
368
+ self._nWorkers.setVisible(False)
369
+ self._nWorkersLabel.setVisible(False)
269
370
 
270
371
  # set up the gui
271
372
  self._nCores.setValue(SlurmSettings.N_CORES_PER_TASK)
272
373
  self._nWorkers.setValue(SlurmSettings.N_TASKS)
273
374
  self._memory.setValue(SlurmSettings.MEMORY_PER_WORKER)
274
- self._queue.setCurrentText(SlurmSettings.PARTITION)
375
+ if self._queue.findText(SlurmSettings.PARTITION) >= 0:
376
+ self._queue.setCurrentText(SlurmSettings.PARTITION)
275
377
  self._nGpu.setValue(n_gpu)
276
378
  self._jobName.setText(SlurmSettings.PROJECT_NAME)
277
379
  self._wallTimeQLE.setText(SlurmSettings.DEFAULT_WALLTIME)
278
- self._pythonVenv.setText(SlurmSettings.PYTHON_VENV)
380
+ self._modulesCB.setChecked(True) # by default we go for modules
381
+ self._preProcessingModeChanged()
382
+ self._partitionChanged()
383
+ self._nGpuChanged()
279
384
 
280
385
  # connect signal / slot
281
386
  self._nCores.valueChanged.connect(self._configurationChanged)
@@ -286,8 +391,20 @@ class SlurmSettingsWidget(qt.QWidget):
286
391
  self._jobName.editingFinished.connect(self._configurationChanged)
287
392
  self._wallTimeQLE.editingFinished.connect(self._configurationChanged)
288
393
  self._pythonVenv.editingFinished.connect(self._configurationChanged)
394
+ self._modulesQLE.editingFinished.connect(self._configurationChanged)
395
+ self._preProcessingButtonGroup.buttonClicked.connect(self._configurationChanged)
289
396
  self._port.sigRangeChanged.connect(self._configurationChanged)
290
397
  self._dashboardPort.valueChanged.connect(self._configurationChanged)
398
+ self._preProcessingButtonGroup.buttonClicked.connect(
399
+ self._preProcessingModeChanged
400
+ )
401
+ self._queue.currentTextChanged.connect(self._partitionChanged)
402
+ self._nGpu.valueChanged.connect(self._nGpuChanged)
403
+ self._gpuCardCB.currentTextChanged.connect(self._configurationChanged)
404
+
405
+ def _nGpuChanged(self, *args, **kwargs):
406
+ nGpu = self.getNGPU()
407
+ self._gpuCardCB.setEnabled(nGpu > 0)
291
408
 
292
409
  def _configurationChanged(self, *args, **kwargs):
293
410
  self.sigConfigChanged.emit()
@@ -341,64 +458,122 @@ class SlurmSettingsWidget(qt.QWidget):
341
458
  self._wallTimeQLE.setText(walltime)
342
459
 
343
460
  def getPythonExe(self):
344
- return self._pythonVenv.text()
461
+ if self._sourceScriptCB.isChecked():
462
+ return self._pythonVenv.text()
463
+ else:
464
+ return None
345
465
 
346
466
  def setPythonExe(self, python_venv):
347
467
  self._pythonVenv.setText(python_venv)
468
+ if python_venv != "":
469
+ self._sourceScriptCB.setChecked(True)
470
+
471
+ def getModulesToLoad(self) -> tuple:
472
+ if self._modulesCB.isChecked():
473
+ return convert_str_to_tuple(self._modulesQLE.text())
474
+ else:
475
+ return tuple()
476
+
477
+ def setModulesToLoad(self, modules: tuple):
478
+ if not isinstance(modules, (tuple, list)):
479
+ raise TypeError(
480
+ f"modules is expected to be a tuple or a list. Get {type(modules)} instead"
481
+ )
482
+ self._modulesQLE.setText(str(modules))
483
+ if len(modules) > 0:
484
+ self._modulesCB.setChecked(True)
485
+
486
+ def getGpuCard(self) -> Optional[str]:
487
+ card = self._gpuCardCB.currentText()
488
+ if card == "any" or self._nGpu == 0:
489
+ return None
490
+ else:
491
+ return card
492
+
493
+ def getSBatchExtraParams(self):
494
+ return {
495
+ "export": self._exportValueCM.currentText(),
496
+ "gpu_card": self.getGpuCard(),
497
+ }
498
+
499
+ def setSBatchExtraParams(self, params: dict):
500
+ export_ = params.get("export", None)
501
+ if export_ is not None:
502
+ index = self._exportValueCM.findText(export_)
503
+ if index >= 0:
504
+ self._exportValueCM.setCurrentIndex(index)
505
+ gpu_card = params.get("gpu_card", None)
506
+ if gpu_card is not None:
507
+ index = self._gpuCardCB.findText("gpu_card")
508
+ if index >= 0:
509
+ self._gpuCardCB.setCurrentIndex(index)
510
+ else:
511
+ # policy when setting the extra params: if doesn't exists / found then won't set it.
512
+ # because they can be part of .ows, this parameter is hidden by default.
513
+ # so safer to use 'any' in the case it is unknown (debatable).
514
+ _logger.warning(f"unable to find gpu {gpu_card}. Won't set it")
348
515
 
349
516
  def setConfiguration(self, config: dict) -> None:
350
- old = self.blockSignals(True)
351
- active_slurm = config.get("active_slurm", None)
352
- if active_slurm is not None:
353
- self._slurmCB.setChecked(active_slurm)
354
-
355
- n_cores = config.get("cpu-per-task", None)
356
- if n_cores is not None:
357
- self.setNCores(n_cores)
358
-
359
- n_workers = config.get("n_tasks", None)
360
- if n_workers is not None:
361
- self.setNWorkers(n_workers)
362
-
363
- memory = config.get("memory", None)
364
- if memory is not None:
365
- if isinstance(memory, str):
366
- memory = memory.replace(" ", "").lower().rstrip("gb")
367
- self.setMemory(int(memory))
368
-
369
- queue_ = config.get("partition", None)
370
- if queue_ is not None:
371
- queue_ = queue_.rstrip("'").rstrip('"')
372
- queue_ = queue_.lstrip("'").lstrip('"')
373
- self.setQueue(queue_)
374
-
375
- n_gpu = config.get("n_gpus", None)
376
- if n_gpu is not None:
377
- self.setNGPU(int(n_gpu))
378
-
379
- project_name = config.get("job_name", None)
380
- if project_name is not None:
381
- self.setProjectName(project_name)
382
-
383
- wall_time = config.get("walltime", None)
384
- if wall_time is not None:
385
- self.setWallTime(wall_time)
386
-
387
- python_venv = config.get("python_venv", None)
388
- if python_venv is not None:
389
- python_venv = python_venv.rstrip("'").rstrip('"')
390
- python_venv = python_venv.lstrip("'").lstrip('"')
391
- self.setPythonExe(python_venv)
392
-
393
- n_jobs = config.get("n_jobs", None)
394
- if n_jobs is not None:
395
- self.setNJobs(n_jobs)
396
-
397
- self.blockSignals(old)
517
+ with block_signals(self):
518
+ active_slurm = config.get("active_slurm", None)
519
+ if active_slurm is not None:
520
+ self._slurmCB.setChecked(active_slurm)
521
+
522
+ n_cores = config.get("cpu-per-task", None)
523
+ if n_cores is not None:
524
+ self.setNCores(n_cores)
525
+
526
+ n_workers = config.get("n_tasks", None)
527
+ if n_workers is not None:
528
+ self.setNWorkers(n_workers)
529
+
530
+ memory = config.get("memory", None)
531
+ if memory is not None:
532
+ if isinstance(memory, str):
533
+ memory = memory.replace(" ", "").lower().rstrip("gb")
534
+ self.setMemory(int(memory))
535
+
536
+ queue_ = config.get("partition", None)
537
+ if queue_ is not None:
538
+ queue_ = queue_.rstrip("'").rstrip('"')
539
+ queue_ = queue_.lstrip("'").lstrip('"')
540
+ self.setQueue(queue_)
541
+
542
+ n_gpu = config.get("n_gpus", None)
543
+ if n_gpu is not None:
544
+ self.setNGPU(int(n_gpu))
545
+
546
+ project_name = config.get("job_name", None)
547
+ if project_name is not None:
548
+ self.setProjectName(project_name)
549
+
550
+ wall_time = config.get("walltime", None)
551
+ if wall_time is not None:
552
+ self.setWallTime(wall_time)
553
+
554
+ python_venv = config.get("python_venv", None)
555
+ if python_venv is not None:
556
+ python_venv = python_venv.rstrip("'").rstrip('"')
557
+ python_venv = python_venv.lstrip("'").lstrip('"')
558
+ self.setPythonExe(python_venv)
559
+
560
+ modules = config.get("modules", None)
561
+ if modules is not None:
562
+ modules = convert_str_to_tuple(modules)
563
+ self.setModulesToLoad(modules)
564
+
565
+ sbatch_extra_params = config.get("sbatch_extra_params", {})
566
+ self.setSBatchExtraParams(sbatch_extra_params)
567
+
568
+ n_jobs = config.get("n_jobs", None)
569
+ if n_jobs is not None:
570
+ self.setNJobs(n_jobs)
571
+ self._preProcessingModeChanged() # make sure modules and python venv is enabled according to the activate mode
572
+
398
573
  self.sigConfigChanged.emit()
399
574
 
400
575
  def getConfiguration(self) -> dict:
401
- return {
576
+ config = {
402
577
  "cpu-per-task": self.getNCores(),
403
578
  "n_tasks": self.getNWorkers(),
404
579
  "n_jobs": self.getNJobs(),
@@ -407,14 +582,48 @@ class SlurmSettingsWidget(qt.QWidget):
407
582
  "n_gpus": self.getNGPU(),
408
583
  "job_name": self.getProjectName(),
409
584
  "walltime": self.getWallTime(),
410
- "python_venv": self.getPythonExe(),
585
+ "sbatch_extra_params": self.getSBatchExtraParams(),
411
586
  }
587
+ if self._modulesCB.isChecked():
588
+ config["modules"] = self.getModulesToLoad()
589
+ elif self._sourceScriptCB.isChecked():
590
+ config["python_venv"] = self.getPythonExe()
591
+ else:
592
+ raise ValueError("'modules' or python environement should be enable")
593
+ return config
412
594
 
413
595
  def getSlurmClusterConfiguration(self):
414
596
  from tomwer.core.cluster import SlurmClusterConfiguration
415
597
 
416
598
  return SlurmClusterConfiguration().from_dict(self.getConfiguration())
417
599
 
600
+ def _preProcessingModeChanged(self):
601
+ self._modulesQLE.setEnabled(self._modulesCB.isChecked())
602
+ self._pythonVenv.setEnabled(self._sourceScriptCB.isChecked())
603
+
604
+ def setConfigurationLevel(self, level: ConfigurationLevel):
605
+ self._sbatchAdvancedParameters.setVisible(level >= ConfigurationLevel.ADVANCED)
606
+
607
+ def _partitionChanged(self, *args, **kwargs):
608
+ partition = self.getQueue()
609
+ gpus = self._getGpus(partition=partition)
610
+ self._gpuCardCB.clear()
611
+ self._gpuCardCB.addItems(gpus)
612
+ self._gpuCardCB.setCurrentText("any")
613
+
614
+ @cache(maxsize=None)
615
+ def _getGpus(self, partition) -> tuple:
616
+ try:
617
+ gpus = get_partition_gpus(partition)
618
+ except Exception as e:
619
+ _logger.error(f"Failed to detect GPU on {partition}. Error is {e}")
620
+ gpus = ("any",)
621
+ else:
622
+ gpus = list(gpus) + [
623
+ "any",
624
+ ]
625
+ return gpus
626
+
418
627
 
419
628
  class _PortRangeSelection(qt.QWidget):
420
629
  sigRangeChanged = qt.Signal()
@@ -102,6 +102,7 @@ class FutureTomwerScanObserverWidget(qt.QWidget):
102
102
  )
103
103
  if future_tomo_obj is not None:
104
104
  self.sigConversionRequested.emit(future_tomo_obj)
105
+ self.observationTable.model().updateIndices()
105
106
  self.observationTable.model().layoutChanged.emit()
106
107
 
107
108
  def _cancelSelected(self, *args, **kwargs):
@@ -123,6 +124,7 @@ class FutureTomwerScanObserverWidget(qt.QWidget):
123
124
  self.observationTable.model().filtered_status = (
124
125
  self.filterWidget.getFilteredStatus()
125
126
  )
127
+ self.observationTable.model().endResetModel()
126
128
 
127
129
  def updateView(self):
128
130
  """
@@ -265,6 +267,16 @@ class _DatasetProcessModel(qt.QAbstractTableModel):
265
267
  del self._tomoObjStatus[future_tomo_obj]
266
268
  self.layoutChanged.emit()
267
269
 
270
+ def updateIndices(self):
271
+ """
272
+ Update tomo object indices when a tomo object has been removed (during a convertion for example)
273
+ """
274
+ tomo_objs = list(self.futureTomoObjs.values())
275
+ self.futureTomoObjs.clear()
276
+ for i_tomo_obj, tomo_obj in enumerate(tomo_objs):
277
+ self.futureTomoObjs[i_tomo_obj] = tomo_obj
278
+ self._computeUnfilteredFutureTomoObjs()
279
+
268
280
  def getUnfilteredFutureTomoObjs(self):
269
281
  return self._filteredFutureTomoObjs
270
282
 
@@ -58,12 +58,16 @@ class TestSlurmWidget(TestCaseQt):
58
58
  "cpu-per-task": SlurmSettings.N_CORES_PER_TASK,
59
59
  "n_tasks": SlurmSettings.N_TASKS,
60
60
  "memory": SlurmSettings.MEMORY_PER_WORKER,
61
- "partition": SlurmSettings.PARTITION,
61
+ "partition": "",
62
62
  "n_gpus": SlurmSettings.N_GPUS_PER_WORKER,
63
63
  "job_name": "tomwer_{scan}_-_{process}_-_{info}",
64
64
  "n_jobs": 1,
65
- "python_venv": "/scisoft/tomotools/activate stable",
65
+ "modules": ("tomotools/stable",),
66
66
  "walltime": "01:00:00",
67
+ "sbatch_extra_params": {
68
+ "export": "NONE",
69
+ "gpu_card": None,
70
+ },
67
71
  }
68
72
  assert dict_res == expected_dict, f"{dict_res} vs {expected_dict}"
69
73
 
@@ -75,6 +79,10 @@ class TestSlurmWidget(TestCaseQt):
75
79
  "memory": 156,
76
80
  "partition": "test-queue",
77
81
  "n_gpus": 5,
82
+ "modules": "mymodule, mysecond/10.3",
83
+ "sbatch_extra_params": {
84
+ "export": "ALL",
85
+ },
78
86
  }
79
87
  )
80
88
 
@@ -83,6 +91,10 @@ class TestSlurmWidget(TestCaseQt):
83
91
  assert self.slurmWidget.getMemory() == 156
84
92
  assert self.slurmWidget.getQueue() == "test-queue"
85
93
  assert self.slurmWidget.getNGPU() == 5
94
+ assert self.slurmWidget.getSBatchExtraParams() == {
95
+ "export": "ALL",
96
+ "gpu_card": None,
97
+ }
86
98
 
87
99
 
88
100
  def test_SlurmSettingsWindow(qtapp): # noqa F811
@@ -36,7 +36,7 @@ from silx.gui import qt
36
36
  from silx.gui.utils.testutils import TestCaseQt
37
37
 
38
38
  from tomwer.core.futureobject import FutureTomwerObject
39
- from tomwer.core.utils.scanutils import MockHDF5
39
+ from tomwer.core.utils.scanutils import MockNXtomo
40
40
  from tomwer.gui.cluster.supervisor import FutureTomwerScanObserverWidget
41
41
 
42
42
 
@@ -52,12 +52,12 @@ class TestSupervisor(TestCaseQt):
52
52
  self._future_tomo_objs = []
53
53
  for i in range(5):
54
54
  # create scan
55
- scan = MockHDF5(
55
+ scan = MockNXtomo(
56
56
  scan_path=os.path.join(self.tempdir, f"scan_test{i}"),
57
57
  n_proj=10,
58
58
  n_ini_proj=10,
59
59
  create_ini_dark=False,
60
- create_ini_ref=False,
60
+ create_ini_flat=False,
61
61
  dim=10,
62
62
  ).scan
63
63
  self._scans.append(scan)
File without changes
@@ -1,35 +1,4 @@
1
- # coding: utf-8
2
- # /*##########################################################################
3
- #
4
- # Copyright (c) 2016-2017 European Synchrotron Radiation Facility
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # of this software and associated documentation files (the "Software"), to deal
8
- # in the Software without restriction, including without limitation the rights
9
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # copies of the Software, and to permit persons to whom the Software is
11
- # furnished to do so, subject to the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be included in
14
- # all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- # THE SOFTWARE.
23
- #
24
- # ###########################################################################*/
25
-
26
- __authors__ = ["H. Payno"]
27
- __license__ = "MIT"
28
- __date__ = "04/08/2020"
29
-
30
-
31
1
  from silx.gui import qt
32
-
33
2
  from tomwer.gui import icons as tomwer_icons
34
3
 
35
4
 
@@ -114,7 +83,7 @@ class FilterAction(qt.QAction):
114
83
  qt.QAction.__init__(self, icon, "filter configuration", parent)
115
84
  self.setToolTip(
116
85
  "If activated will only display the configuration"
117
- "for the active nabu phase"
86
+ "for the active nabu step"
118
87
  )
119
88
  self.setCheckable(True)
120
89
  self.setShortcut(qt.QKeySequence(qt.Qt.Key_F))
@@ -0,0 +1,22 @@
1
+ from silx.utils.enum import Enum as _Enum
2
+
3
+
4
+ class ConfigurationLevel(_Enum):
5
+ REQUIRED = "required"
6
+ OPTIONAL = "optional"
7
+ ADVANCED = "advanced"
8
+
9
+ def _get_num_value(self) -> int:
10
+ if self is self.REQUIRED:
11
+ return 0
12
+ elif self is self.OPTIONAL:
13
+ return 1
14
+ elif self is self.ADVANCED:
15
+ return 2
16
+
17
+ def __le__(self, other):
18
+ if not isinstance(other, ConfigurationLevel):
19
+ raise TypeError(
20
+ f"other is expected to be an instance of ConfigurationLevel. {type(other)} provided"
21
+ )
22
+ return self._get_num_value() <= other._get_num_value()