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,17 +29,18 @@ __date__ = "06/12/2021"
29
29
 
30
30
 
31
31
  import logging
32
- from typing import Optional
32
+ from typing import Optional, Union
33
33
 
34
34
  from silx.gui import qt
35
35
 
36
36
  from tomwer.core.process.reconstruction.nabu.utils import (
37
37
  _NabuStages,
38
- _RingCorrectionMethod,
38
+ RingCorrectionMethod,
39
39
  )
40
40
  from tomwer.gui.reconstruction.nabu.nabuconfig.base import _NabuStageConfigBase
41
41
  from tomwer.gui.utils.scrollarea import QComboBoxIgnoreWheel as QComboBox
42
42
  from tomwer.gui.utils.scrollarea import QDoubleSpinBoxIgnoreWheel as QDoubleSpinBox
43
+ from tomwer.gui.utils.scrollarea import QSpinBoxIgnoreWheel as QSpinBox
43
44
  from tomwer.utils import docstring
44
45
 
45
46
  _logger = logging.getLogger(__name__)
@@ -78,6 +79,9 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
78
79
  self._dffSigmaQDSB.setMinimum(0.0)
79
80
  self._dffSigmaQDSB.setDecimals(2)
80
81
  self._dffSigmaQDSB.setSingleStep(0.1)
82
+ self._dffSigmaQDSB.setToolTip(
83
+ "Sigma value to give to the double flat field unsharp mask"
84
+ )
81
85
  self.layout().addWidget(self._dffSigmaQDSB, 1, 3, 1, 1)
82
86
  self.registerWidget(self._flatFieldCB, "required")
83
87
  self._dffOptWidgets = [
@@ -92,16 +96,16 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
92
96
  self.registerWidget(self._sinoRingCorrectionCB, "required")
93
97
 
94
98
  self._sinoRingCorrectionMthd = QComboBox(parent=self, scrollArea=scrollArea)
95
- for method in _RingCorrectionMethod:
99
+ for method in RingCorrectionMethod:
96
100
  self._sinoRingCorrectionMthd.addItem(method.value)
97
101
  ## force method to be None by default
98
- idx = self._sinoRingCorrectionMthd.findText(_RingCorrectionMethod.NONE.value)
102
+ idx = self._sinoRingCorrectionMthd.findText(RingCorrectionMethod.NONE.value)
99
103
  self._sinoRingCorrectionMthd.setCurrentIndex(idx)
100
104
 
101
105
  self.layout().addWidget(self._sinoRingCorrectionMthd, 2, 2, 1, 1)
102
106
  self.registerWidget(self._sinoRingCorrectionMthd, "required")
103
107
 
104
- self._sinoRingsOpts = SinoRingsOptions(parent=self)
108
+ self._sinoRingsOpts = SinoRingsOptions(parent=self, scrollArea=scrollArea)
105
109
  self.layout().addWidget(self._sinoRingsOpts, 3, 1, 1, 3)
106
110
 
107
111
  ## ccd filter
@@ -232,8 +236,8 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
232
236
  self._sinoRingCorrectionMthd.currentIndexChanged.connect(
233
237
  self._sinoRingCorrectionChanged
234
238
  )
235
- self._sinoRingsOpts._levels.valueChanged.connect(self._sinoRingOptsChanged)
236
- self._sinoRingsOpts._sigma.valueChanged.connect(self._sinoRingOptsChanged)
239
+ self._sinoRingsOpts._levelsMunch.valueChanged.connect(self._sinoRingOptsChanged)
240
+ self._sinoRingsOpts._sigmaMunch.valueChanged.connect(self._sinoRingOptsChanged)
237
241
 
238
242
  self._tiltCorrection.toggled.connect(self._tiltCorrectionChanged)
239
243
  self._tiltCorrection.sigChanged.connect(self._tiltCorrectionChanged)
@@ -266,9 +270,13 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
266
270
  self._signalConfChanged("take_logarithm")
267
271
 
268
272
  def _sinoRingCorrectionChanged(self, *args, **kwargs):
269
- self._sinoRingsOpts.setVisible(
270
- self.getSinoRingcorrectionMethod() in (_RingCorrectionMethod.MUNCH.value,)
271
- )
273
+ method = self.getSinoRingcorrectionMethod()
274
+ if method is not RingCorrectionMethod.NONE.value:
275
+ self._sinoRingsOpts.setVisible(True)
276
+ self._sinoRingsOpts.setMethod(method)
277
+ else:
278
+ self._sinoRingsOpts.setVisible(False)
279
+
272
280
  self._signalConfChanged("sino_rings_correction")
273
281
 
274
282
  def _sinoRingOptsChanged(self, *args, **kwargs):
@@ -341,8 +349,11 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
341
349
  opt_as_dict = {}
342
350
  for opt in options.split(";"):
343
351
  opt = opt.replace(" ", "")
344
- key, value = opt.split("=")
345
- opt_as_dict[key] = value
352
+ if len(opt.split("=")) == 2:
353
+ key, value = opt.split("=")
354
+ opt_as_dict[key] = value
355
+ else:
356
+ _logger.info(f"ignore option {opt}. Invalid synthax")
346
357
 
347
358
  self._sinoRingsOpts.setOptions(opt_as_dict)
348
359
 
@@ -412,8 +423,8 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
412
423
  sino_rings_correction = conf.get("sino_rings_correction", None)
413
424
  if sino_rings_correction is not None:
414
425
  if sino_rings_correction == "":
415
- sino_rings_correction = _RingCorrectionMethod.NONE
416
- sino_rings_correction = _RingCorrectionMethod.from_value(
426
+ sino_rings_correction = RingCorrectionMethod.NONE
427
+ sino_rings_correction = RingCorrectionMethod.from_value(
417
428
  sino_rings_correction
418
429
  ).value
419
430
  idx = self._sinoRingCorrectionMthd.findText(sino_rings_correction)
@@ -431,32 +442,212 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
431
442
 
432
443
 
433
444
  class SinoRingsOptions(qt.QWidget):
434
- def __init__(self, parent=None, *args, **kwargs):
445
+ _VO_DIMS = ("horizontaly", "horizontaly and vertically")
446
+
447
+ def __init__(self, parent=None, scrollArea=None, *args, **kwargs):
435
448
  super().__init__(parent, *args, **kwargs)
449
+ self._method = None
436
450
  self.setLayout(qt.QFormLayout())
437
- self._sigma = qt.QDoubleSpinBox(self)
438
- self._sigma.setRange(0.0, 2147483647)
439
- self.layout().addRow("sigma", self._sigma)
440
-
441
- self._levels = qt.QSpinBox(self)
442
- self._levels.setRange(0, 2147483647)
443
- self.layout().addRow("levels", self._levels)
444
-
451
+ self.layout().setContentsMargins(0, 0, 0, 0)
452
+ self.layout().setSpacing(0)
453
+ # munch parameters
454
+ self._sigmaMunchLabel = qt.QLabel("sigma", self)
455
+ self._sigmaMunch = QDoubleSpinBox(self, scrollArea=scrollArea)
456
+ self._sigmaMunch.setRange(0.0, 2147483647)
457
+ self.layout().addRow(self._sigmaMunchLabel, self._sigmaMunch)
458
+
459
+ self._levelsMunchLabel = qt.QLabel("levels", self)
460
+ self._levelsMunch = QSpinBox(self, scrollArea=scrollArea)
461
+ self._levelsMunch.setRange(0, 2147483647)
462
+ self.layout().addRow(self._levelsMunchLabel, self._levelsMunch)
463
+
464
+ self._paddingMunch = qt.QCheckBox("padding", self)
465
+ self.layout().addWidget(self._paddingMunch)
466
+
467
+ # vo parameters
468
+ self._snrVOLabel = qt.QLabel("snr", self)
469
+ self._snrVO = QDoubleSpinBox(self, scrollArea=scrollArea)
470
+ self._snrVO.setMinimum(0.0)
471
+ tooltip = "Ratio used to locate large stripes. Greater is less sensitive."
472
+ self._snrVO.setToolTip(tooltip)
473
+ self._snrVOLabel.setToolTip(tooltip)
474
+ self.layout().addRow(self._snrVOLabel, self._snrVO)
475
+
476
+ self._laSizeVOLabel = qt.QLabel("la_size", self)
477
+ self._laSizeVO = QSpinBox(self, scrollArea=scrollArea)
478
+ self._laSizeVO.setMinimum(0)
479
+ tooltip = "Window size of the median filter to remove large stripes."
480
+ self._laSizeVO.setToolTip(tooltip)
481
+ self._laSizeVOLabel.setToolTip(tooltip)
482
+ self.layout().addRow(self._laSizeVOLabel, self._laSizeVO)
483
+
484
+ self._smSizeVOLabel = qt.QLabel("sm_size", self)
485
+ self._smSizeVO = QSpinBox(self, scrollArea=scrollArea)
486
+ self._smSizeVO.setMinimum(0)
487
+ tooltip = "Window size of the median filter to remove small-to-medium stripes."
488
+ self._laSizeVO.setToolTip(tooltip)
489
+ self._smSizeVOLabel.setToolTip(tooltip)
490
+ self.layout().addRow(self._smSizeVOLabel, self._smSizeVO)
491
+
492
+ self._dimVOLabel = qt.QLabel("dimension", self)
493
+ self._dimVO = QComboBox(self, scrollArea=scrollArea)
494
+ self._dimVO.addItems(self._VO_DIMS)
495
+ self.layout().addRow(self._dimVOLabel, self._dimVO)
496
+
497
+ # sino mean deringer
498
+ self._sigmaLowLabel = qt.QLabel("signal low", self)
499
+ self._sigmaLow = QDoubleSpinBox(self, scrollArea=scrollArea)
500
+ self._sigmaLow.setMinimum(0.0)
501
+ self._sigmaHighLabel = qt.QLabel("signal high", self)
502
+ self.layout().addRow(self._sigmaLowLabel, self._sigmaLow)
503
+
504
+ self._sigmaHigh = QDoubleSpinBox(self, scrollArea=scrollArea)
505
+ self._sigmaHigh.setMinimum(0.0)
506
+ tooltip = (
507
+ "sigma low and sigma high values are defining the standard deviation of "
508
+ "gaussian(sigma_low) * (1 - gaussian(sigma_high)). \n"
509
+ "High values of sigma mean stronger effect of associated filters."
510
+ )
511
+ self._sigmaHigh.setToolTip(tooltip)
512
+ self._sigmaLow.setToolTip(tooltip)
513
+ self.layout().addRow(self._sigmaHighLabel, self._sigmaHigh)
445
514
  # set up
446
- self._sigma.setValue(1.0)
447
- self._levels.setValue(10)
515
+ self.resetConfiguration()
516
+
517
+ def resetConfiguration(self):
518
+ self.setMethod(method=RingCorrectionMethod.MUNCH)
519
+ self._levelsMunch.setValue(10)
520
+ self._sigmaMunch.setValue(1.0)
521
+ self._paddingMunch.setChecked(False)
522
+
523
+ self._sigmaHigh.setValue(30.0)
524
+ self._sigmaLow.setValue(0.0)
525
+
526
+ self._snrVO.setValue(3.0)
527
+ self._laSizeVO.setValue(51)
528
+ self._smSizeVO.setValue(21)
529
+
530
+ def getVoDim(self):
531
+ if self._dimVO.currentText() == self._VO_DIMS[0]:
532
+ return 1
533
+ elif self._dimVO.currentText() == self._VO_DIMS[1]:
534
+ return 2
535
+ else:
536
+ raise NotImplementedError
537
+
538
+ def setVoDim(self, dim: Union[int, str]):
539
+ if dim in ("1", 1, self._VO_DIMS[0]):
540
+ self._dimVO.setCurrentText(self._VO_DIMS[0])
541
+ elif dim in ("2", 2, self._VO_DIMS[1]):
542
+ self._dimVO.setCurrentText(self._VO_DIMS[1])
543
+ else:
544
+ raise NotImplementedError(f"dim {dim} not handled")
448
545
 
449
546
  def getOptions(self) -> dict:
450
- return {
451
- "sigma": self._sigma.value(),
452
- "levels": self._levels.value(),
453
- }
547
+ if self.getMethod() is RingCorrectionMethod.NONE:
548
+ return {}
549
+ elif self.getMethod() is RingCorrectionMethod.MUNCH:
550
+ return {
551
+ "sigma": self._sigmaMunch.value(),
552
+ "levels": self._levelsMunch.value(),
553
+ "padding": self._paddingMunch.isChecked(),
554
+ }
555
+ elif self.getMethod() is RingCorrectionMethod.VO:
556
+ return {
557
+ "snr": self._snrVO.value(),
558
+ "la_size": self._laSizeVO.value(),
559
+ "sm_size": self._smSizeVO.value(),
560
+ "dim": self.getVoDim(),
561
+ }
562
+ elif self.getMethod() in (
563
+ RingCorrectionMethod.MEAN_DIVISION,
564
+ RingCorrectionMethod.MEAN_SUBTRACTION,
565
+ ):
566
+ return {
567
+ "filter_cutoff": (self._sigmaLow.value(), self._sigmaHigh.value()),
568
+ }
569
+ else:
570
+ raise NotImplementedError
454
571
 
455
572
  def setOptions(self, options: dict) -> None:
573
+ # handle munch propertoies
456
574
  if "sigma" in options:
457
- self._sigma.setValue(float(options["sigma"]))
575
+ self._sigmaMunch.setValue(float(options["sigma"]))
458
576
  if "levels" in options:
459
- self._levels.setValue(int(options["levels"]))
577
+ self._levelsMunch.setValue(int(options["levels"]))
578
+ padding = options.get("padding")
579
+ if padding is not None:
580
+ self._paddingMunch.setChecked(padding in (True, 1, "1", "True"))
581
+ # handle VO properties
582
+ snr = options.get("snr")
583
+ if snr is not None:
584
+ self._snrVO.setValue(float(snr))
585
+ la_size = options.get("la_size")
586
+ if la_size is not None:
587
+ self._laSizeVO.setValue(int(la_size))
588
+ sm_size = options.get("sm_size")
589
+ if sm_size is not None:
590
+ self._smSizeVO.setValue(int(sm_size))
591
+ dim = options.get("dim")
592
+ if dim is not None:
593
+ self.setVoDim(dim)
594
+ # handle mean subtraction or division options
595
+ filter_cutoff = options.get("filter_cutoff")
596
+ if filter_cutoff is not None:
597
+ low_pass, high_pass = filter_cutoff
598
+ self._sigmaLow.setValue(float(low_pass))
599
+ self._sigmaHigh.setValue(float(high_pass))
600
+
601
+ def setMethod(self, method: RingCorrectionMethod):
602
+ method = RingCorrectionMethod.from_value(method)
603
+ self._method = method
604
+ # handle munch options
605
+ self._sigmaMunch.setVisible(method is RingCorrectionMethod.MUNCH)
606
+ self._sigmaMunchLabel.setVisible(method is RingCorrectionMethod.MUNCH)
607
+ self._levelsMunch.setVisible(method is RingCorrectionMethod.MUNCH)
608
+ self._levelsMunchLabel.setVisible(method is RingCorrectionMethod.MUNCH)
609
+ self._paddingMunch.setVisible(method is RingCorrectionMethod.MUNCH)
610
+ # handle VO options
611
+ self._snrVO.setVisible(method is RingCorrectionMethod.VO)
612
+ self._snrVOLabel.setVisible(method is RingCorrectionMethod.VO)
613
+ self._laSizeVO.setVisible(method is RingCorrectionMethod.VO)
614
+ self._laSizeVOLabel.setVisible(method is RingCorrectionMethod.VO)
615
+ self._smSizeVO.setVisible(method is RingCorrectionMethod.VO)
616
+ self._smSizeVOLabel.setVisible(method is RingCorrectionMethod.VO)
617
+ self._dimVO.setVisible(method is RingCorrectionMethod.VO)
618
+ self._dimVOLabel.setVisible(method is RingCorrectionMethod.VO)
619
+ # mean subtractions / division deringer
620
+ self._sigmaLow.setVisible(
621
+ method
622
+ in (
623
+ RingCorrectionMethod.MEAN_DIVISION,
624
+ RingCorrectionMethod.MEAN_SUBTRACTION,
625
+ )
626
+ )
627
+ self._sigmaLowLabel.setVisible(
628
+ method
629
+ in (
630
+ RingCorrectionMethod.MEAN_DIVISION,
631
+ RingCorrectionMethod.MEAN_SUBTRACTION,
632
+ )
633
+ )
634
+ self._sigmaHigh.setVisible(
635
+ method
636
+ in (
637
+ RingCorrectionMethod.MEAN_DIVISION,
638
+ RingCorrectionMethod.MEAN_SUBTRACTION,
639
+ )
640
+ )
641
+ self._sigmaHighLabel.setVisible(
642
+ method
643
+ in (
644
+ RingCorrectionMethod.MEAN_DIVISION,
645
+ RingCorrectionMethod.MEAN_SUBTRACTION,
646
+ )
647
+ )
648
+
649
+ def getMethod(self) -> RingCorrectionMethod:
650
+ return self._method
460
651
 
461
652
 
462
653
  class TiltCorrection(qt.QGroupBox):
@@ -35,6 +35,7 @@ from silx.gui import qt
35
35
  from silx.gui.dialog.DataFileDialog import DataFileDialog
36
36
  from silx.utils.enum import Enum as _Enum
37
37
 
38
+ from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
38
39
  from tomwer.core.process.reconstruction.nabu.nabuslices import NabuSliceMode
39
40
  from tomwer.core.process.reconstruction.nabu.utils import (
40
41
  _NabuFBPFilterType,
@@ -85,16 +86,13 @@ class SliceGroupBox(qt.QGroupBox):
85
86
 
86
87
  # connect signal / slot
87
88
  self._modeCB.currentIndexChanged.connect(self._updateSliceQLEVisibilty)
88
- self._modeCB.currentIndexChanged.connect(self._triggerSlicesChanged)
89
- self._sliceQLE.editingFinished.connect(self._triggerSlicesChanged)
90
- self.toggled.connect(self._triggerSlicesChanged)
89
+ self._modeCB.currentIndexChanged.connect(self.sigSlicesChanged)
90
+ self._sliceQLE.editingFinished.connect(self.sigSlicesChanged)
91
+ self.toggled.connect(self.sigSlicesChanged)
91
92
 
92
93
  def _updateSliceQLEVisibilty(self, *args, **kwargs):
93
94
  self._sliceQLE.setVisible(self.getMode() == NabuSliceMode.OTHER)
94
95
 
95
- def _triggerSlicesChanged(self):
96
- self.sigSlicesChanged.emit()
97
-
98
96
  def setMode(self, mode: NabuSliceMode):
99
97
  mode = NabuSliceMode.from_value(mode)
100
98
  item_index = self._modeCB.findText(mode.value)
@@ -303,55 +301,74 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
303
301
  # come with an issue as we are on a scroll area
304
302
  self._slicesWidget.setFocusPolicy(qt.Qt.FocusPolicy.NoFocus)
305
303
 
304
+ # axis
305
+ self._axisLabel = qt.QLabel("reconstruction plane", self)
306
+ self._axisLabel.setToolTip("Over which axis the slice must be picked")
307
+ self.layout().addWidget(self._axisLabel)
308
+ self._axisQCB = qt.QComboBox(self)
309
+ axis_tooltips = {
310
+ NabuPlane.YZ.value: "along axis x (aka axis 2 - expected to be slow)",
311
+ NabuPlane.XZ.value: "along axis y (aka axis 1 - expected to be slow)",
312
+ NabuPlane.XY.value: "along axis Z (aka axis 0 - fastest)",
313
+ }
314
+ for item, tooltip in axis_tooltips.items():
315
+ self._axisQCB.addItem(item)
316
+ self._axisQCB.setItemData(
317
+ self._axisQCB.findText(item),
318
+ tooltip,
319
+ qt.Qt.ToolTipRole,
320
+ )
321
+ self.layout().addWidget(self._axisQCB, 1, 1, 1, 1)
322
+
306
323
  # method
307
324
  self._methodLabel = qt.QLabel("method", self)
308
- self.layout().addWidget(self._methodLabel, 1, 0, 1, 1)
325
+ self.layout().addWidget(self._methodLabel, 2, 0, 1, 1)
309
326
  self._methodQCB = QComboBoxIgnoreWheel(parent=self, scrollArea=scrollArea)
310
327
  for method in _NabuReconstructionMethods:
311
328
  self._methodQCB.addItem(method.value)
312
- self.layout().addWidget(self._methodQCB, 1, 1, 1, 1)
329
+ self.layout().addWidget(self._methodQCB, 2, 1, 1, 1)
313
330
  self.registerWidget(self._methodLabel, "required")
314
331
  self.registerWidget(self._methodQCB, "required")
315
332
 
316
333
  # angle_offset
317
334
  self._labelOffsetLabel = qt.QLabel("angle offset (in degree)", self)
318
- self.layout().addWidget(self._labelOffsetLabel, 2, 0, 1, 1)
335
+ self.layout().addWidget(self._labelOffsetLabel, 3, 0, 1, 1)
319
336
  self._angleOffsetQDSB = QDoubleSpinBoxIgnoreWheel(self, scrollArea)
320
337
  self._angleOffsetQDSB.setMaximum(-180)
321
338
  self._angleOffsetQDSB.setMaximum(180)
322
- self.layout().addWidget(self._angleOffsetQDSB, 2, 1, 1, 1)
339
+ self.layout().addWidget(self._angleOffsetQDSB, 3, 1, 1, 1)
323
340
  self.registerWidget(self._labelOffsetLabel, "advanced")
324
341
  self.registerWidget(self._angleOffsetQDSB, "advanced")
325
342
 
326
343
  # fbp filter type
327
344
  self._fbpFilterCB = qt.QCheckBox("fbp filter", self)
328
- self.layout().addWidget(self._fbpFilterCB, 3, 0, 1, 1)
345
+ self.layout().addWidget(self._fbpFilterCB, 4, 0, 1, 1)
329
346
  self._fbpFilterType = QComboBoxIgnoreWheel(self, scrollArea)
330
347
  for filter_type in _NabuFBPFilterType:
331
348
  self._fbpFilterType.addItem(filter_type.value)
332
- self.layout().addWidget(self._fbpFilterType, 3, 1, 1, 1)
349
+ self.layout().addWidget(self._fbpFilterType, 4, 1, 1, 1)
333
350
  self.registerWidget(self._fbpFilterCB, "advanced")
334
351
  self.registerWidget(self._fbpFilterType, "advanced")
335
352
 
336
353
  # padding type
337
354
  self._paddingTypeLabel = qt.QLabel("padding type", self)
338
- self.layout().addWidget(self._paddingTypeLabel, 4, 0, 1, 1)
355
+ self.layout().addWidget(self._paddingTypeLabel, 5, 0, 1, 1)
339
356
  self._paddingType = QComboBoxIgnoreWheel(self, scrollArea)
340
357
  for fbp_padding_type in _NabuPaddingType:
341
358
  self._paddingType.addItem(fbp_padding_type.value)
342
- self.layout().addWidget(self._paddingType, 4, 1, 1, 1)
359
+ self.layout().addWidget(self._paddingType, 5, 1, 1, 1)
343
360
  self.registerWidget(self._paddingTypeLabel, "optional")
344
361
  self.registerWidget(self._paddingType, "optional")
345
362
 
346
363
  # sub region
347
364
  self._subRegionSelector = _NabuReconstructionSubRegion(parent=self)
348
- self.layout().addWidget(self._subRegionSelector, 6, 0, 1, 2)
365
+ self.layout().addWidget(self._subRegionSelector, 7, 0, 1, 2)
349
366
 
350
367
  # iterations
351
368
  self._iterationsLabel = qt.QLabel("iterations", self)
352
- self.layout().addWidget(self._iterationsLabel, 7, 0, 1, 1)
369
+ self.layout().addWidget(self._iterationsLabel, 8, 0, 1, 1)
353
370
  self._iterationSB = qt.QSpinBox(parent=self)
354
- self.layout().addWidget(self._iterationSB, 7, 1, 1, 1)
371
+ self.layout().addWidget(self._iterationSB, 8, 1, 1, 1)
355
372
  self._iterationSB.setMinimum(1)
356
373
  self._iterationSB.setMaximum(9999)
357
374
  # not supported for now so hidden
@@ -362,14 +379,14 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
362
379
  self._binSubSamplingGB = _BinSubSampling(
363
380
  "binning and subsampling", parent=self, scrollArea=scrollArea
364
381
  )
365
- self.layout().addWidget(self._binSubSamplingGB, 8, 0, 1, 2)
382
+ self.layout().addWidget(self._binSubSamplingGB, 9, 0, 1, 2)
366
383
 
367
384
  # optimization algorithm:
368
385
  # set has default value for now, because has only one at the moment
369
386
 
370
387
  # weight total variation
371
388
  self._tvLabel = qt.QLabel("total variation weight", self)
372
- self.layout().addWidget(self._tvLabel, 9, 0, 1, 1)
389
+ self.layout().addWidget(self._tvLabel, 10, 0, 1, 1)
373
390
  self._totalVariationWeight = qt.QDoubleSpinBox(self)
374
391
  self._totalVariationWeight.setMinimum(0.0)
375
392
  self._totalVariationWeight.setMaximum(1.0)
@@ -385,7 +402,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
385
402
  self._preconditioningFilter.setToolTip(
386
403
  'Whether to enable "filter ' 'preconditioning" for iterative' " methods"
387
404
  )
388
- self.layout().addWidget(self._preconditioningFilter, 9, 0, 1, 2)
405
+ self.layout().addWidget(self._preconditioningFilter, 10, 0, 1, 2)
389
406
  # not supported for now so hidden
390
407
  self._preconditioningFilter.hide()
391
408
 
@@ -394,7 +411,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
394
411
  self._positivityConstraintCB.setToolTip(
395
412
  "Whether to enforce a " "positivity constraint in the " "reconstruction."
396
413
  )
397
- self.layout().addWidget(self._positivityConstraintCB, 10, 0, 1, 2)
414
+ self.layout().addWidget(self._positivityConstraintCB, 11, 0, 1, 2)
398
415
  # not supported for now so hidden
399
416
  self._positivityConstraintCB.hide()
400
417
 
@@ -403,28 +420,28 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
403
420
  self._clipOuterCircleCB.setToolTip(
404
421
  "Whether to set to zero voxels falling outside of the reconstruction region"
405
422
  )
406
- self.layout().addWidget(self._clipOuterCircleCB, 11, 0, 1, 2)
423
+ self.layout().addWidget(self._clipOuterCircleCB, 12, 0, 1, 2)
407
424
  self.registerWidget(self._clipOuterCircleCB, "optional")
408
425
 
409
426
  # centered axis option
410
427
  self._centeredAxisCB = qt.QCheckBox("centered axis", self)
411
428
  self._centeredAxisCB.setToolTip("")
412
- self.layout().addWidget(self._centeredAxisCB, 12, 0, 1, 2)
429
+ self.layout().addWidget(self._centeredAxisCB, 13, 0, 1, 2)
413
430
  self.registerWidget(self._centeredAxisCB, "optional")
414
431
 
415
432
  # translation movement file
416
433
  self._transMvtFileLabel = qt.QLabel("translation movement file", self)
417
- self.layout().addWidget(self._transMvtFileLabel, 21, 0, 1, 1)
434
+ self.layout().addWidget(self._transMvtFileLabel, 22, 0, 1, 1)
418
435
  self._transMvtFileWidget = TranslationMvtFileWidget(self)
419
- self.layout().addWidget(self._transMvtFileWidget, 21, 1, 1, 1)
436
+ self.layout().addWidget(self._transMvtFileWidget, 22, 1, 1, 1)
420
437
  self.registerWidget(self._transMvtFileLabel, "advanced")
421
438
  self.registerWidget(self._transMvtFileWidget, "advanced")
422
439
 
423
440
  # angle files (if the user want's to overwrite rotation angles)
424
441
  self._angleFileLabel = qt.QLabel("angles file", self)
425
- self.layout().addWidget(self._angleFileLabel, 22, 0, 1, 1)
442
+ self.layout().addWidget(self._angleFileLabel, 23, 0, 1, 1)
426
443
  self._anglesFileWidget = AnglesFileWidget(self)
427
- self.layout().addWidget(self._anglesFileWidget, 22, 1, 1, 1)
444
+ self.layout().addWidget(self._anglesFileWidget, 23, 1, 1, 1)
428
445
  self.registerWidget(self._angleFileLabel, "advanced")
429
446
  self.registerWidget(self._anglesFileWidget, "advanced")
430
447
 
@@ -434,6 +451,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
434
451
  self.layout().addWidget(spacer, 200, 1, 1, 1)
435
452
 
436
453
  # set up
454
+ self.setNabuPlane("XY")
437
455
  self._fbpFilterCB.setChecked(True)
438
456
  fbp_item = self._methodQCB.findText(_NabuReconstructionMethods.FBP.value)
439
457
  self._methodQCB.setCurrentIndex(fbp_item)
@@ -450,6 +468,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
450
468
  self._centeredAxisCB.setChecked(False)
451
469
 
452
470
  # connect signal / slot
471
+ self._axisQCB.currentIndexChanged.connect(self._slicesChanged)
453
472
  self._methodQCB.currentIndexChanged.connect(self._methodChanged)
454
473
  self._angleOffsetQDSB.editingFinished.connect(self._angleOffsetChanged)
455
474
  self._fbpFilterCB.toggled.connect(self._FBPFilterTypeChanged)
@@ -631,6 +650,14 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
631
650
  def setCenteredAxis(self, checked: bool):
632
651
  self._centeredAxisCB.setChecked(checked)
633
652
 
653
+ def getNabuPlane(self) -> NabuPlane:
654
+ """return over which axis we expect to do the reconstruction"""
655
+ return NabuPlane.from_value(self._axisQCB.currentText())
656
+
657
+ def setNabuPlane(self, axis: typing.Union[str, NabuPlane]):
658
+ axis = NabuPlane.from_value(axis)
659
+ self._axisQCB.setCurrentText(axis.value)
660
+
634
661
  @docstring(_NabuStageConfigBase)
635
662
  def getConfiguration(self) -> dict:
636
663
  fbp_filter_type = self.getFBPFilterType()
@@ -640,6 +667,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
640
667
  fbp_filter_type = fbp_filter_type.value
641
668
  config = {
642
669
  "method": self.getMethod().value,
670
+ "slice_plane": self.getNabuPlane().value,
643
671
  "angles_file": self.getAnglesFile(),
644
672
  "axis_correction_file": "", # not managed for now
645
673
  "angle_offset": self.getAngleOffset(),
@@ -692,6 +720,8 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
692
720
  self.setClipOuterCircle(bool(config["clip_outer_circle"]))
693
721
  if "centered_axis" in config:
694
722
  self.setCenteredAxis(bool(config["centered_axis"]))
723
+ if "slice_plane" in config:
724
+ self.setNabuPlane(config["slice_plane"])
695
725
  self._subRegionSelector.setConfiguration(config=config)
696
726
 
697
727
  def _signalConfChanged(self, param):
@@ -108,23 +108,27 @@ class NabuFlowControl(qt.QWidget):
108
108
  self._iniProcessWidgets.sigWidgetActivated.connect(
109
109
  functools.partial(self._updateActiveProcess, _NabuStages.INI)
110
110
  )
111
- self._iniProcessWidgets.sigWidgetDeactivated.connect(self._activeProcessUnset)
111
+ self._iniProcessWidgets.sigWidgetDeactivated.connect(self.sigResetConfiguration)
112
112
  self._preProcessWidgets.sigWidgetActivated.connect(
113
113
  functools.partial(self._updateActiveProcess, _NabuStages.PRE)
114
114
  )
115
- self._preProcessWidgets.sigWidgetDeactivated.connect(self._activeProcessUnset)
115
+ self._preProcessWidgets.sigWidgetDeactivated.connect(self.sigResetConfiguration)
116
116
  self._phaseProcessWidgets.sigWidgetActivated.connect(
117
117
  functools.partial(self._updateActiveProcess, _NabuStages.PHASE)
118
118
  )
119
- self._phaseProcessWidgets.sigWidgetDeactivated.connect(self._activeProcessUnset)
119
+ self._phaseProcessWidgets.sigWidgetDeactivated.connect(
120
+ self.sigResetConfiguration
121
+ )
120
122
  self._processWidgets.sigWidgetActivated.connect(
121
123
  functools.partial(self._updateActiveProcess, _NabuStages.PROC)
122
124
  )
123
- self._processWidgets.sigWidgetDeactivated.connect(self._activeProcessUnset)
125
+ self._processWidgets.sigWidgetDeactivated.connect(self.sigResetConfiguration)
124
126
  self._postProcessWidgets.sigWidgetActivated.connect(
125
127
  functools.partial(self._updateActiveProcess, _NabuStages.POST)
126
128
  )
127
- self._postProcessWidgets.sigWidgetDeactivated.connect(self._activeProcessUnset)
129
+ self._postProcessWidgets.sigWidgetDeactivated.connect(
130
+ self.sigResetConfiguration
131
+ )
128
132
 
129
133
  # set up
130
134
  self.setIniprocVisible(False)
@@ -133,9 +137,6 @@ class NabuFlowControl(qt.QWidget):
133
137
  self.setProcVisible(True)
134
138
  self.setPostVisible(True)
135
139
 
136
- def _activeProcessUnset(self):
137
- self.sigResetConfiguration.emit()
138
-
139
140
  def _updateActiveProcess(self, stage):
140
141
  stage = _NabuStages.from_value(stage)
141
142
 
@@ -396,14 +397,8 @@ class NabuFlowArea(qt.QWidget):
396
397
 
397
398
  # connect signal / slot
398
399
  self._addRmWidget.sigRmProcess.connect(self._control._removeActiveProcess)
399
- self._control.sigConfigurationChanged.connect(self._repeatConfigSignal)
400
- self._control.sigResetConfiguration.connect(self._repeatResetConfigSignal)
401
-
402
- def _repeatConfigSignal(self, *args):
403
- self.sigConfigurationChanged.emit(*args)
404
-
405
- def _repeatResetConfigSignal(self):
406
- self.sigResetConfiguration.emit()
400
+ self._control.sigConfigurationChanged.connect(self.sigConfigurationChanged)
401
+ self._control.sigResetConfiguration.connect(self.sigResetConfiguration)
407
402
 
408
403
  @docstring(NabuFlowControl)
409
404
  def setIniProcessing(self, processes, icons):
@@ -464,12 +459,9 @@ class _AddRemoveProcessWidget(qt.QWidget):
464
459
 
465
460
  # connect signal / slot
466
461
  self._addButton.pressed.connect(self._addProcess)
467
- self._rmButton.pressed.connect(self._rmProcess)
462
+ self._rmButton.pressed.connect(self.sigRmProcess)
468
463
 
469
464
  def _addProcess(self):
470
465
  # should be able to add a process from ini, post, processing and pre
471
466
 
472
467
  raise NotImplementedError(" not implemented, to be defined")
473
-
474
- def _rmProcess(self):
475
- self.sigRmProcess.emit()