tomwer 1.3.27__py3-none-any.whl → 1.4.0rc0__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 (632) hide show
  1. orangecontrib/tomwer/orange/managedprocess.py +1 -29
  2. orangecontrib/tomwer/orange/settings.py +2 -28
  3. orangecontrib/tomwer/tests/TestAcquisition.py +220 -0
  4. orangecontrib/tomwer/tutorials/append_raw_darks_and_flats_frames_to_NXtomos.ows +2 -2
  5. orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth1.ows +1 -1
  6. orangecontrib/tomwer/tutorials/{icat_publication.ows → drac_publication.ows} +7 -21
  7. orangecontrib/tomwer/tutorials/id16b/ID16b_full_volume.ows +22 -0
  8. orangecontrib/tomwer/tutorials/id16b/ID16b_insitu.ows +302 -0
  9. orangecontrib/tomwer/tutorials/id16b/ID16b_normalization.ows +218 -0
  10. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +29 -24
  11. orangecontrib/tomwer/tutorials/test_cor.ows +19 -0
  12. orangecontrib/tomwer/tutorials/volume_casting_on_slurm.ows +54 -0
  13. orangecontrib/tomwer/widgets/__init__.py +3 -5
  14. orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +35 -54
  15. orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +1 -31
  16. orangecontrib/tomwer/widgets/control/AdvancementOW.py +1 -29
  17. orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +5 -4
  18. orangecontrib/tomwer/widgets/control/DataListenerOW.py +1 -29
  19. orangecontrib/tomwer/widgets/control/DataSelectorOW.py +11 -30
  20. orangecontrib/tomwer/widgets/control/DataTransfertOW.py +2 -28
  21. orangecontrib/tomwer/widgets/control/DataValidatorOW.py +1 -28
  22. orangecontrib/tomwer/widgets/control/DataWatcherOW.py +1 -28
  23. orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +48 -51
  24. orangecontrib/tomwer/widgets/control/EmailOW.py +12 -2
  25. orangecontrib/tomwer/widgets/control/FilterOW.py +1 -28
  26. orangecontrib/tomwer/widgets/control/NXTomomillOW.py +37 -53
  27. orangecontrib/tomwer/widgets/control/NXtomoConcatenate.py +21 -20
  28. orangecontrib/tomwer/widgets/control/NotifierOW.py +9 -28
  29. orangecontrib/tomwer/widgets/control/ReduceDarkFlatSelectorOW.py +3 -2
  30. orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +1 -27
  31. orangecontrib/tomwer/widgets/control/TimerOW.py +9 -28
  32. orangecontrib/tomwer/widgets/control/TomoObjSeriesOW.py +58 -0
  33. orangecontrib/tomwer/widgets/control/VolumeSelector.py +8 -30
  34. orangecontrib/tomwer/widgets/control/icons/nxtomomill.svg +173 -119
  35. orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.png +0 -0
  36. orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.svg +55 -195
  37. orangecontrib/tomwer/widgets/control/icons/{tomoobjserie.svg → tomoobjseries.svg} +2 -2
  38. orangecontrib/tomwer/widgets/dataportal/PublishProcessedDataOW.py +172 -0
  39. orangecontrib/tomwer/widgets/{icat → dataportal}/__init__.py +2 -2
  40. orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +2 -29
  41. orangecontrib/tomwer/widgets/debugtools/ObjectInspectorOW.py +1 -29
  42. orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +48 -73
  43. orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +48 -75
  44. orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +5 -30
  45. orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +51 -52
  46. orangecontrib/tomwer/widgets/other/PythonScriptOW.py +22 -10
  47. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +48 -49
  48. orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +22 -68
  49. orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +3 -30
  50. orangecontrib/tomwer/widgets/reconstruction/NabuHelicalPrepareWeightsDoubleOW.py +21 -19
  51. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +7 -70
  52. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +40 -85
  53. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +15 -40
  54. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +13 -35
  55. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +2 -30
  56. orangecontrib/tomwer/widgets/stitching/ZStitchingConfigOW.py +11 -11
  57. orangecontrib/tomwer/widgets/utils.py +2 -29
  58. orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +1 -27
  59. orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -27
  60. orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +1 -1
  61. orangecontrib/tomwer/widgets/visualization/RadioStackOW.py +2 -28
  62. orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +1 -27
  63. orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +1 -27
  64. orangecontrib/tomwer/widgets/visualization/SliceStackOW.py +2 -28
  65. tomwer/__init__.py +3 -28
  66. tomwer/__main__.py +8 -4
  67. tomwer/app/__init__.py +2 -0
  68. tomwer/app/axis.py +8 -7
  69. tomwer/app/canvas.py +23 -29
  70. tomwer/app/canvas_launcher/config.py +14 -102
  71. tomwer/app/canvas_launcher/environ.py +5 -8
  72. tomwer/app/canvas_launcher/mainwindow.py +175 -69
  73. tomwer/app/canvas_launcher/splash.py +1 -3
  74. tomwer/app/canvas_launcher/utils.py +47 -0
  75. tomwer/app/canvas_launcher/widgetsscheme.py +3 -10
  76. tomwer/app/diffframe.py +2 -0
  77. tomwer/app/imagekeyeditor.py +2 -1
  78. tomwer/app/imagekeyupgrader.py +2 -0
  79. tomwer/app/multicor.py +5 -2
  80. tomwer/app/multipag.py +7 -4
  81. tomwer/app/nabuapp.py +2 -1
  82. tomwer/app/nxtomoeditor.py +17 -12
  83. tomwer/app/patchrawdarkflat.py +2 -0
  84. tomwer/app/radiostack.py +3 -2
  85. tomwer/app/reducedarkflat.py +3 -0
  86. tomwer/app/samplemoved.py +2 -0
  87. tomwer/app/scanviewer.py +2 -0
  88. tomwer/app/sinogramviewer.py +2 -0
  89. tomwer/app/slicestack.py +11 -13
  90. tomwer/app/stitching/common.py +431 -0
  91. tomwer/app/stopdatalistener.py +3 -0
  92. tomwer/app/ystitching.py +26 -0
  93. tomwer/app/zstitching.py +8 -363
  94. tomwer/core/__init__.py +2 -28
  95. tomwer/core/cluster/__init__.py +3 -0
  96. tomwer/core/cluster/cluster.py +10 -26
  97. tomwer/core/futureobject.py +17 -43
  98. tomwer/core/log/__init__.py +2 -0
  99. tomwer/core/log/processlog.py +0 -28
  100. tomwer/core/process/cluster/supervisor.py +52 -34
  101. tomwer/core/process/conditions/filters.py +3 -28
  102. tomwer/core/process/control/datalistener/datalistener.py +7 -75
  103. tomwer/core/process/control/datalistener/rpcserver.py +8 -38
  104. tomwer/core/process/control/datawatcher/datawatcher.py +11 -40
  105. tomwer/core/process/control/datawatcher/datawatcherobserver.py +30 -64
  106. tomwer/core/process/control/datawatcher/datawatcherprocess.py +11 -32
  107. tomwer/core/process/control/datawatcher/edfdwprocess.py +2 -27
  108. tomwer/core/process/control/datawatcher/hdf5dwprocess.py +1 -26
  109. tomwer/core/process/control/datawatcher/status.py +1 -26
  110. tomwer/core/process/control/emailnotifier.py +11 -23
  111. tomwer/core/process/control/nxtomoconcatenate.py +20 -18
  112. tomwer/core/process/control/nxtomomill.py +9 -44
  113. tomwer/core/process/control/scanlist.py +0 -27
  114. tomwer/core/process/control/scantransfer.py +15 -13
  115. tomwer/core/process/control/scanvalidator.py +4 -30
  116. tomwer/core/process/control/{test → tests}/test_concatenate_nxtomos.py +5 -5
  117. tomwer/core/process/control/timer.py +1 -27
  118. tomwer/core/process/control/tomoobjseries.py +12 -0
  119. tomwer/core/process/drac/binning.py +37 -0
  120. tomwer/core/process/drac/dracbase.py +170 -0
  121. tomwer/core/process/drac/gallery.py +109 -0
  122. tomwer/core/process/drac/output.py +12 -0
  123. tomwer/core/process/drac/processeddataset.py +147 -0
  124. tomwer/core/process/drac/publish.py +118 -0
  125. tomwer/core/process/drac/rawdataset.py +142 -0
  126. tomwer/core/process/drac/tests/test_gallery.py +71 -0
  127. tomwer/core/process/drac/tests/test_icat_processed_dataset.py +80 -0
  128. tomwer/core/process/drac/tests/test_icat_raw_dataset.py +90 -0
  129. tomwer/core/process/edit/darkflatpatch.py +1 -28
  130. tomwer/core/process/edit/imagekeyeditor.py +4 -32
  131. tomwer/core/process/edit/nxtomoeditor.py +307 -0
  132. tomwer/core/process/edit/tests/test_darkflatpatch.py +243 -0
  133. tomwer/core/process/edit/tests/test_imagekey_editor.py +99 -0
  134. tomwer/core/process/output.py +9 -2
  135. tomwer/core/process/reconstruction/__init__.py +0 -26
  136. tomwer/core/process/reconstruction/axis/anglemode.py +1 -29
  137. tomwer/core/process/reconstruction/axis/axis.py +63 -111
  138. tomwer/core/process/reconstruction/axis/mode.py +5 -3
  139. tomwer/core/process/reconstruction/axis/params.py +5 -146
  140. tomwer/core/process/reconstruction/axis/projectiontype.py +0 -28
  141. tomwer/core/process/reconstruction/darkref/darkrefs.py +14 -39
  142. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +7 -39
  143. tomwer/core/process/reconstruction/darkref/params.py +1 -28
  144. tomwer/core/process/reconstruction/nabu/castvolume.py +19 -34
  145. tomwer/core/process/reconstruction/nabu/nabucommon.py +18 -43
  146. tomwer/core/process/reconstruction/nabu/nabuscores.py +47 -48
  147. tomwer/core/process/reconstruction/nabu/nabuslices.py +59 -105
  148. tomwer/core/process/reconstruction/nabu/nabuvolume.py +44 -70
  149. tomwer/core/process/reconstruction/nabu/plane.py +10 -0
  150. tomwer/core/process/reconstruction/nabu/settings.py +1 -28
  151. tomwer/core/process/reconstruction/nabu/target.py +0 -28
  152. tomwer/core/process/reconstruction/nabu/test/test_castvolume.py +116 -0
  153. tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +277 -0
  154. tomwer/core/process/reconstruction/nabu/test/test_nabunormalization.py +199 -0
  155. tomwer/core/process/reconstruction/nabu/utils.py +11 -60
  156. tomwer/core/process/reconstruction/normalization/normalization.py +2 -32
  157. tomwer/core/process/reconstruction/normalization/params.py +3 -35
  158. tomwer/core/process/reconstruction/output.py +14 -19
  159. tomwer/core/process/reconstruction/paramsbase.py +4 -33
  160. tomwer/core/process/reconstruction/saaxis/params.py +5 -33
  161. tomwer/core/process/reconstruction/saaxis/saaxis.py +18 -47
  162. tomwer/core/process/reconstruction/sadeltabeta/params.py +2 -31
  163. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +16 -44
  164. tomwer/core/process/reconstruction/scores/params.py +9 -39
  165. tomwer/core/process/reconstruction/scores/scores.py +10 -42
  166. tomwer/core/process/reconstruction/tests/__init__.py +0 -0
  167. tomwer/core/process/reconstruction/tests/test_axis.py +46 -0
  168. tomwer/core/process/reconstruction/tests/test_darkref.py +33 -0
  169. tomwer/core/process/reconstruction/{test → tests}/test_saaxis.py +1 -27
  170. tomwer/core/process/reconstruction/tests/test_sadeltabeta.py +48 -0
  171. tomwer/core/process/script/python.py +1 -27
  172. tomwer/core/process/script/tests/test_script.py +41 -0
  173. tomwer/core/process/stitching/metadataholder.py +5 -4
  174. tomwer/core/process/stitching/nabustitcher.py +35 -5
  175. tomwer/core/process/stitching/tests/test_metadataholder.py +17 -0
  176. tomwer/core/process/task.py +20 -63
  177. tomwer/core/process/tests/__init__.py +0 -0
  178. tomwer/core/process/{test → tests}/test_axis.py +1 -79
  179. tomwer/core/process/{test → tests}/test_conditions.py +1 -28
  180. tomwer/core/process/{test → tests}/test_dark_and_flat.py +1 -27
  181. tomwer/core/process/{test → tests}/test_data_listener.py +1 -27
  182. tomwer/core/process/{test → tests}/test_data_transfer.py +2 -28
  183. tomwer/core/process/{test → tests}/test_data_watcher.py +1 -27
  184. tomwer/core/process/{test → tests}/test_nabu.py +4 -33
  185. tomwer/core/process/{test → tests}/test_normalization.py +1 -26
  186. tomwer/core/process/{test → tests}/test_timer.py +1 -27
  187. tomwer/core/process/utils.py +2 -31
  188. tomwer/core/process/visualization/dataviewer.py +1 -26
  189. tomwer/core/process/visualization/diffviewer.py +1 -26
  190. tomwer/core/process/visualization/imagestackviewer.py +0 -26
  191. tomwer/core/process/visualization/radiostack.py +0 -26
  192. tomwer/core/process/visualization/samplemoved.py +0 -28
  193. tomwer/core/process/visualization/sinogramviewer.py +0 -27
  194. tomwer/core/process/visualization/slicestack.py +0 -28
  195. tomwer/core/process/visualization/tests/test_data_viewer.py +12 -0
  196. tomwer/core/process/visualization/tests/test_diff_viewer.py +12 -0
  197. tomwer/core/process/visualization/tests/test_image_stack_viewer.py +14 -0
  198. tomwer/core/process/visualization/tests/test_radio_stack.py +12 -0
  199. tomwer/core/process/visualization/tests/test_sample_moved.py +14 -0
  200. tomwer/core/process/visualization/tests/test_sinogram_viewer.py +13 -0
  201. tomwer/core/process/visualization/tests/test_slice_stack.py +13 -0
  202. tomwer/core/process/visualization/tests/test_volume_viewer.py +12 -0
  203. tomwer/core/process/visualization/volumeviewer.py +0 -29
  204. tomwer/core/scan/__init__.py +3 -27
  205. tomwer/core/scan/blissscan.py +5 -34
  206. tomwer/core/scan/edfscan.py +19 -53
  207. tomwer/core/scan/hdf5scan.py +2 -2
  208. tomwer/core/scan/nxtomoscan.py +46 -54
  209. tomwer/core/scan/scanbase.py +104 -200
  210. tomwer/core/scan/scanfactory.py +11 -41
  211. tomwer/core/scan/tests/__init__.py +0 -0
  212. tomwer/core/scan/tests/test_edf.py +25 -0
  213. tomwer/core/scan/tests/test_future_scan.py +35 -0
  214. tomwer/core/scan/tests/test_nxtomoscan.py +143 -0
  215. tomwer/core/scan/{test → tests}/test_process_registration.py +1 -28
  216. tomwer/core/settings.py +18 -40
  217. tomwer/core/tests/__init__.py +0 -0
  218. tomwer/core/tests/test_scanutils.py +26 -0
  219. tomwer/core/{test → tests}/test_utils.py +1 -28
  220. tomwer/core/tomwer_object.py +4 -0
  221. tomwer/core/utils/__init__.py +2 -0
  222. tomwer/core/utils/char.py +0 -28
  223. tomwer/core/utils/deprecation.py +12 -38
  224. tomwer/core/utils/dictutils.py +1 -3
  225. tomwer/core/utils/ftseriesutils.py +1 -27
  226. tomwer/core/utils/gpu.py +0 -28
  227. tomwer/core/utils/image.py +8 -39
  228. tomwer/core/utils/locker.py +1 -28
  229. tomwer/core/utils/logconfig.py +0 -27
  230. tomwer/core/utils/normalization.py +4 -31
  231. tomwer/core/utils/nxtomoutils.py +8 -38
  232. tomwer/core/utils/resource.py +0 -26
  233. tomwer/core/utils/scanutils.py +23 -52
  234. tomwer/core/utils/slurm.py +7 -30
  235. tomwer/core/utils/spec.py +6 -6
  236. tomwer/core/utils/tests/__init__.py +0 -0
  237. tomwer/core/utils/tests/test_image.py +30 -0
  238. tomwer/core/utils/tests/test_nxtomo.py +38 -0
  239. tomwer/core/utils/tests/test_scan_utils.py +46 -0
  240. tomwer/core/utils/tests/test_time.py +6 -0
  241. tomwer/core/utils/threads.py +0 -26
  242. tomwer/core/utils/time.py +0 -27
  243. tomwer/core/volume/__init__.py +4 -0
  244. tomwer/core/volume/edfvolume.py +1 -28
  245. tomwer/core/volume/hdf5volume.py +1 -28
  246. tomwer/core/volume/jp2kvolume.py +1 -27
  247. tomwer/core/volume/rawvolume.py +1 -28
  248. tomwer/core/volume/tests/test_volumes.py +21 -0
  249. tomwer/core/volume/tiffvolume.py +1 -28
  250. tomwer/core/volume/volumebase.py +5 -0
  251. tomwer/core/volume/volumefactory.py +7 -33
  252. tomwer/gui/__init__.py +0 -28
  253. tomwer/gui/cluster/__init__.py +2 -0
  254. tomwer/gui/cluster/slurm.py +297 -95
  255. tomwer/gui/cluster/supervisor.py +1 -27
  256. tomwer/gui/cluster/tests/__init__.py +0 -0
  257. tomwer/gui/cluster/{test → tests}/test_cluster.py +21 -26
  258. tomwer/gui/cluster/{test → tests}/test_supervisor.py +1 -27
  259. tomwer/gui/conditions/__init__.py +2 -0
  260. tomwer/gui/conditions/filter.py +1 -26
  261. tomwer/gui/configuration/__init__.py +2 -0
  262. tomwer/gui/control/__init__.py +2 -0
  263. tomwer/gui/control/actions.py +2 -28
  264. tomwer/gui/control/datadiscovery.py +4 -3
  265. tomwer/gui/control/datalist.py +64 -69
  266. tomwer/gui/control/datalistener.py +1 -39
  267. tomwer/gui/control/datareacheractions.py +1 -28
  268. tomwer/gui/control/datatransfert.py +2 -29
  269. tomwer/gui/control/datavalidator.py +3 -37
  270. tomwer/gui/control/datawatcher/__init__.py +0 -28
  271. tomwer/gui/control/datawatcher/configuration.py +1 -28
  272. tomwer/gui/control/datawatcher/datawatcher.py +3 -32
  273. tomwer/gui/control/datawatcher/datawatcherobserver.py +2 -28
  274. tomwer/gui/control/history.py +5 -35
  275. tomwer/gui/control/nxtomomill.py +3 -30
  276. tomwer/gui/control/observations.py +61 -55
  277. tomwer/gui/control/reducedarkflatselector.py +24 -20
  278. tomwer/gui/control/scanselectorwidget.py +2 -28
  279. tomwer/gui/control/selectorwidgetbase.py +17 -17
  280. tomwer/gui/control/series/__init__.py +0 -0
  281. tomwer/gui/control/{serie/seriecreator.py → series/seriescreator.py} +214 -235
  282. tomwer/gui/control/series/serieswaiter.py +0 -0
  283. tomwer/gui/control/series/test/test_creator.py +424 -0
  284. tomwer/gui/control/series/test/test_nxtomo_concatenate.py +21 -0
  285. tomwer/gui/control/singletomoobj.py +1 -1
  286. tomwer/gui/control/tests/__init__.py +0 -0
  287. tomwer/gui/control/tests/test_datalist.py +47 -0
  288. tomwer/gui/control/{test → tests}/test_datalistener.py +1 -28
  289. tomwer/gui/control/tests/test_datavalidator.py +27 -0
  290. tomwer/gui/control/{test → tests}/test_inputwidget.py +1 -27
  291. tomwer/gui/control/tests/test_process_manager.py +38 -0
  292. tomwer/gui/control/tests/test_scan_observations.py +23 -0
  293. tomwer/gui/control/tests/test_scanselector.py +42 -0
  294. tomwer/gui/control/{test → tests}/test_scanvalidator.py +1 -27
  295. tomwer/gui/control/{test → tests}/test_volume_dialog.py +2 -30
  296. tomwer/gui/control/{test → tests}/test_volumeselector.py +1 -27
  297. tomwer/gui/control/volumeselectorwidget.py +2 -30
  298. tomwer/gui/dataportal/__init__.py +2 -0
  299. tomwer/gui/{icat → dataportal}/createscreenshots.py +3 -2
  300. tomwer/gui/dataportal/gallery.py +133 -0
  301. tomwer/gui/dataportal/outputformat.py +0 -0
  302. tomwer/gui/dataportal/publish.py +96 -0
  303. tomwer/gui/dataportal/tests/test_create_screenshots_gui.py +23 -0
  304. tomwer/gui/dataportal/tests/test_gallery_gui.py +21 -0
  305. tomwer/gui/debugtools/__init__.py +2 -0
  306. tomwer/gui/debugtools/datasetgenerator.py +1 -30
  307. tomwer/gui/debugtools/objectinspector.py +1 -29
  308. tomwer/gui/dialog/QDataDialog.py +89 -0
  309. tomwer/gui/{qfolderdialog.py → dialog/QVolumeDialog.py} +8 -107
  310. tomwer/gui/dialog/__init__.py +1 -0
  311. tomwer/gui/edit/__init__.py +2 -0
  312. tomwer/gui/edit/dkrfpatch.py +52 -87
  313. tomwer/gui/edit/imagekeyeditor.py +18 -54
  314. tomwer/gui/edit/nxtomoeditor.py +113 -300
  315. tomwer/gui/edit/nxtomowarmer.py +3 -2
  316. tomwer/gui/edit/tests/__init__.py +0 -0
  317. tomwer/gui/edit/{test → tests}/test_dkrf_patch.py +3 -29
  318. tomwer/gui/edit/{test → tests}/test_image_key_editor.py +1 -27
  319. tomwer/gui/edit/{test → tests}/test_nx_editor.py +45 -23
  320. tomwer/gui/icons.py +28 -66
  321. tomwer/gui/illustrations.py +4 -34
  322. tomwer/gui/imagefromfile.py +5 -30
  323. tomwer/gui/metadataloader.py +36 -0
  324. tomwer/gui/qconfigfile.py +3 -0
  325. tomwer/gui/qlefilesystem.py +3 -0
  326. tomwer/gui/reconstruction/__init__.py +2 -0
  327. tomwer/gui/reconstruction/axis/AxisMainWindow.py +264 -0
  328. tomwer/gui/reconstruction/axis/AxisOptionsWidget.py +153 -0
  329. tomwer/gui/reconstruction/axis/AxisSettingsWidget.py +776 -0
  330. tomwer/gui/reconstruction/axis/AxisWidget.py +526 -0
  331. tomwer/gui/reconstruction/axis/CalculationWidget.py +374 -0
  332. tomwer/gui/reconstruction/axis/CompareImages.py +11 -44
  333. tomwer/gui/reconstruction/axis/ControlWidget.py +277 -0
  334. tomwer/gui/reconstruction/axis/InputWidget.py +491 -0
  335. tomwer/gui/reconstruction/axis/ManualFramesSelection.py +168 -0
  336. tomwer/gui/reconstruction/axis/__init__.py +2 -2
  337. tomwer/gui/reconstruction/darkref/__init__.py +0 -27
  338. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +5 -34
  339. tomwer/gui/reconstruction/darkref/darkrefwidget.py +1 -27
  340. tomwer/gui/reconstruction/nabu/castvolume.py +40 -59
  341. tomwer/gui/reconstruction/nabu/check.py +7 -33
  342. tomwer/gui/reconstruction/nabu/nabuconfig/base.py +7 -34
  343. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +6 -5
  344. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +10 -69
  345. tomwer/gui/reconstruction/nabu/nabuconfig/output.py +3 -47
  346. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +54 -36
  347. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +103 -54
  348. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +116 -65
  349. tomwer/gui/reconstruction/nabu/nabuflow.py +31 -61
  350. tomwer/gui/reconstruction/nabu/platform.py +94 -0
  351. tomwer/gui/reconstruction/nabu/slices.py +81 -45
  352. tomwer/gui/reconstruction/nabu/slurm.py +1 -27
  353. tomwer/gui/reconstruction/nabu/test/test_cast_volume.py +82 -0
  354. tomwer/gui/reconstruction/nabu/test/test_check.py +66 -0
  355. tomwer/gui/reconstruction/nabu/test/test_ctf.py +46 -0
  356. tomwer/gui/reconstruction/nabu/test/test_helical.py +21 -0
  357. tomwer/gui/reconstruction/nabu/test/test_nabu_preprocessing.py +81 -0
  358. tomwer/gui/reconstruction/nabu/volume.py +62 -90
  359. tomwer/gui/reconstruction/normalization/intensity.py +5 -32
  360. tomwer/gui/reconstruction/normalization/test/test_intensity.py +89 -0
  361. tomwer/gui/reconstruction/saaxis/corrangeselector.py +16 -49
  362. tomwer/gui/reconstruction/saaxis/dimensionwidget.py +56 -96
  363. tomwer/gui/reconstruction/saaxis/saaxis.py +17 -38
  364. tomwer/gui/reconstruction/saaxis/sliceselector.py +8 -39
  365. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +19 -37
  366. tomwer/gui/reconstruction/scores/control.py +2 -30
  367. tomwer/gui/reconstruction/scores/scoreplot.py +19 -48
  368. tomwer/gui/reconstruction/tests/__init__.py +0 -0
  369. tomwer/gui/reconstruction/{test → tests}/test_axis.py +23 -49
  370. tomwer/gui/reconstruction/{test → tests}/test_nabu.py +8 -31
  371. tomwer/gui/reconstruction/{test → tests}/test_saaxis.py +10 -37
  372. tomwer/gui/reconstruction/{test → tests}/test_sadeltabeta.py +1 -26
  373. tomwer/gui/samplemoved/__init__.py +2 -30
  374. tomwer/gui/samplemoved/selectiontable.py +3 -33
  375. tomwer/gui/settings.py +7 -0
  376. tomwer/gui/stackplot.py +33 -661
  377. tomwer/gui/stacks.py +261 -135
  378. tomwer/gui/stitching/SingleAxisStitchingWidget.py +326 -0
  379. tomwer/gui/stitching/StitchingOptionsWidget.py +438 -0
  380. tomwer/gui/stitching/StitchingWindow.py +586 -0
  381. tomwer/gui/stitching/__init__.py +2 -0
  382. tomwer/gui/stitching/alignment.py +90 -0
  383. tomwer/gui/stitching/axisorderedlist.py +44 -34
  384. tomwer/gui/stitching/config/axisparams.py +23 -11
  385. tomwer/gui/stitching/config/output.py +6 -5
  386. tomwer/gui/stitching/config/positionoveraxis.py +313 -51
  387. tomwer/gui/stitching/config/stitchingstrategies.py +22 -16
  388. tomwer/gui/stitching/config/tests/test_axisparams.py +25 -0
  389. tomwer/gui/stitching/config/tomoobjdetails.py +3 -5
  390. tomwer/gui/stitching/normalization.py +1 -0
  391. tomwer/gui/stitching/preview.py +59 -0
  392. tomwer/gui/stitching/singleaxis.py +57 -0
  393. tomwer/gui/stitching/stitchandbackground.py +3 -2
  394. tomwer/gui/stitching/stitching_preview.py +44 -36
  395. tomwer/gui/stitching/stitching_raw.py +5 -3
  396. tomwer/gui/stitching/tests/test_ZStitchingWindow.py +88 -0
  397. tomwer/gui/stitching/tests/test_axis_ordered_list.py +21 -0
  398. tomwer/gui/stitching/tests/test_normalization.py +27 -0
  399. tomwer/gui/stitching/tests/test_preview.py +68 -0
  400. tomwer/gui/stitching/tests/test_stitching_raw.py +110 -0
  401. tomwer/gui/stitching/tests/utils.py +92 -0
  402. tomwer/gui/stitching/utils.py +14 -0
  403. tomwer/gui/stitching/z_stitching/fineestimation.py +4 -32
  404. tomwer/gui/stitching/z_stitching/tests/test_fine_estimation.py +35 -0
  405. tomwer/gui/stitching/z_stitching/tests/test_raw_estimation.py +215 -0
  406. tomwer/gui/stitching/z_stitching/tests/test_stitching_window.py +51 -0
  407. tomwer/gui/tests/__init__.py +0 -0
  408. tomwer/gui/tests/test_axis_gui.py +27 -0
  409. tomwer/gui/{test → tests}/test_qfolder_dialog.py +1 -1
  410. tomwer/gui/utils/RangeWidget.py +44 -0
  411. tomwer/gui/utils/buttons.py +4 -3
  412. tomwer/gui/utils/completer.py +2 -33
  413. tomwer/gui/utils/flow.py +11 -40
  414. tomwer/gui/utils/gpu.py +60 -0
  415. tomwer/gui/utils/illustrations.py +1 -26
  416. tomwer/gui/utils/inputwidget.py +35 -73
  417. tomwer/gui/utils/lineselector/lineselector.py +9 -46
  418. tomwer/gui/utils/loadingmode.py +81 -0
  419. tomwer/gui/utils/qt_utils.py +9 -0
  420. tomwer/gui/utils/sandboxes.py +1 -26
  421. tomwer/gui/utils/scandescription.py +2 -31
  422. tomwer/gui/utils/scrollarea.py +6 -55
  423. tomwer/gui/utils/slider.py +4 -28
  424. tomwer/gui/utils/splashscreen.py +0 -28
  425. tomwer/gui/utils/step.py +14 -13
  426. tomwer/gui/utils/tests/test_completer.py +41 -0
  427. tomwer/gui/utils/tests/test_line_selector.py +21 -0
  428. tomwer/gui/utils/tests/test_splashscreen.py +8 -0
  429. tomwer/gui/utils/tests/test_vignettes.py +68 -0
  430. tomwer/gui/utils/unitsystem.py +15 -69
  431. tomwer/gui/utils/utils.py +4 -5
  432. tomwer/gui/utils/vignettes.py +10 -41
  433. tomwer/gui/utils/waiterthread.py +0 -26
  434. tomwer/gui/visualization/__init__.py +2 -0
  435. tomwer/gui/visualization/dataviewer.py +68 -421
  436. tomwer/gui/visualization/diffviewer/diffviewer.py +2 -30
  437. tomwer/gui/visualization/diffviewer/shiftwidget.py +4 -29
  438. tomwer/gui/visualization/fullscreenplot.py +5 -5
  439. tomwer/gui/visualization/imagestack.py +403 -0
  440. tomwer/gui/visualization/nxtomometadata.py +0 -4
  441. tomwer/gui/visualization/reconstructionparameters.py +14 -32
  442. tomwer/gui/visualization/scanoverview.py +33 -66
  443. tomwer/gui/visualization/sinogramviewer.py +2 -28
  444. tomwer/gui/visualization/test/__init__.py +0 -28
  445. tomwer/gui/visualization/test/test_dataviewer.py +1 -28
  446. tomwer/gui/visualization/test/test_diffviewer.py +1 -28
  447. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +0 -5
  448. tomwer/gui/visualization/test/test_reconstruction_parameters.py +1 -27
  449. tomwer/gui/visualization/test/test_sinogramviewer.py +1 -28
  450. tomwer/gui/visualization/test/test_stacks.py +184 -115
  451. tomwer/gui/visualization/test/test_volumeviewer.py +3 -2
  452. tomwer/gui/visualization/tomoobjoverview.py +2 -2
  453. tomwer/gui/visualization/volumeoverview.py +3 -2
  454. tomwer/gui/visualization/volumeviewer.py +47 -43
  455. tomwer/io/__init__.py +2 -0
  456. tomwer/io/utils/h5pyutils.py +1 -27
  457. tomwer/io/utils/test/test_raw_and_processed_data.py +10 -0
  458. tomwer/io/utils/test/test_utils.py +67 -0
  459. tomwer/io/utils/utils.py +2 -31
  460. tomwer/resources/__init__.py +13 -33
  461. tomwer/resources/gui/icons/edit_downstream.svg +114 -0
  462. tomwer/resources/gui/icons/edit_upstream.svg +112 -0
  463. tomwer/resources/gui/icons/free_edition.svg +23 -0
  464. tomwer/resources/gui/icons/icat_gallery_opts.png +0 -0
  465. tomwer/resources/gui/icons/icat_gallery_opts.svg +80 -0
  466. tomwer/resources/gui/icons/search.png +0 -0
  467. tomwer/resources/gui/icons/search.svg +23 -0
  468. tomwer/resources/gui/icons/warning.png +0 -0
  469. tomwer/synctools/__init__.py +2 -0
  470. tomwer/synctools/axis.py +1 -27
  471. tomwer/synctools/darkref.py +1 -26
  472. tomwer/synctools/datalistener.py +1 -27
  473. tomwer/synctools/datatransfert.py +2 -27
  474. tomwer/synctools/imageloaderthread.py +1 -28
  475. tomwer/synctools/rsyncmanager.py +1 -25
  476. tomwer/synctools/saaxis.py +1 -26
  477. tomwer/synctools/sadeltabeta.py +1 -26
  478. tomwer/synctools/stacks/control/datalistener.py +1 -26
  479. tomwer/synctools/stacks/processingstack.py +4 -33
  480. tomwer/synctools/stacks/reconstruction/axis.py +2 -31
  481. tomwer/synctools/stacks/reconstruction/castvolume.py +12 -43
  482. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +3 -26
  483. tomwer/synctools/stacks/reconstruction/nabu.py +1 -26
  484. tomwer/synctools/stacks/reconstruction/normalization.py +1 -26
  485. tomwer/synctools/stacks/reconstruction/saaxis.py +1 -26
  486. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +1 -26
  487. tomwer/synctools/tests/__init__.py +0 -0
  488. tomwer/synctools/{test → tests}/test_darkRefs.py +16 -40
  489. tomwer/synctools/{test → tests}/test_foldertransfer.py +2 -33
  490. tomwer/synctools/utils/scanstages.py +2 -31
  491. tomwer/tests/__init__.py +1 -0
  492. tomwer/tests/app/test_stitching.py +95 -0
  493. tomwer/tests/datasets.py +1 -5
  494. tomwer/tests/orangecontrib/tomwer/widgets/cluster/tests/test_future_supervisorow.py +48 -0
  495. tomwer/tests/orangecontrib/tomwer/widgets/cluster/tests/test_slurm_clusterow.py +40 -0
  496. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_advancement.py +8 -0
  497. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_data_validator.py +55 -0
  498. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_datadiscovery.py +129 -0
  499. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_datalistener.py +111 -0
  500. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_dataselector.py +69 -0
  501. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_datawatcher.py +411 -0
  502. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_emailow.py +29 -0
  503. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_notifier.py +24 -0
  504. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_nxtomo_concatenate_ow.py +64 -0
  505. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_nxtomomill.py +133 -0
  506. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_reduce_dark_flat_selector.py +40 -0
  507. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_singletomoobj.py +40 -0
  508. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_timerow.py +25 -0
  509. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_tomoobj_series.py +96 -0
  510. tomwer/tests/orangecontrib/tomwer/widgets/control/tests/test_volume_selector.py +69 -0
  511. orangecontrib/tomwer/widgets/edit/test/test_image_key_editor.py → tomwer/tests/orangecontrib/tomwer/widgets/debugtools/tests/test_dataset_generator.py +17 -16
  512. tomwer/tests/orangecontrib/tomwer/widgets/debugtools/tests/test_object_inspector.py +36 -0
  513. {orangecontrib/tomwer/widgets/edit/test → tomwer/tests/orangecontrib/tomwer/widgets/edit/tests}/test_dark_flat_patch.py +1 -27
  514. tomwer/tests/orangecontrib/tomwer/widgets/edit/tests/test_image_key_editor.py +30 -0
  515. tomwer/tests/orangecontrib/tomwer/widgets/edit/tests/test_nxtomo_editor.py +138 -0
  516. tomwer/tests/orangecontrib/tomwer/widgets/other/tests/test_pythonscript.py +31 -0
  517. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_axis.py +215 -0
  518. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_cast_volumeow.py +58 -0
  519. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_dark_refs_widget.py +136 -0
  520. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_delta_beta_selector.py +15 -0
  521. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_i_norm.py +200 -0
  522. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_nabu_helical_prepare_weights_double.py +20 -0
  523. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_nabu_volume.py +74 -0
  524. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_nabu_widget.py +107 -0
  525. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_sa_delta_beta.py +194 -0
  526. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_saaxis.py +194 -0
  527. tomwer/tests/orangecontrib/tomwer/widgets/stitching/tests/test_zstitching.py +313 -0
  528. tomwer/tests/orangecontrib/tomwer/widgets/tests/test_conditions.py +85 -0
  529. tomwer/tests/orangecontrib/tomwer/widgets/tests/test_darkref.py +225 -0
  530. tomwer/tests/orangecontrib/tomwer/widgets/tests/test_foldertransfert.py +105 -0
  531. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_dataviewerow.py +57 -0
  532. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_diffviewerow.py +39 -0
  533. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_nxtomo_metadata_viewer.py +29 -0
  534. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_radio_stackow.py +31 -0
  535. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_sample_movedow.py +46 -0
  536. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_sinogram_viewerow.py +31 -0
  537. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_slice_stackow.py +31 -0
  538. tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_volume_viewerow.py +32 -0
  539. tomwer/tests/test_ewoks/test_conversion.py +104 -0
  540. tomwer/tests/test_ewoks/test_single_node_execution.py +87 -0
  541. tomwer/tests/test_ewoks/test_workflows.py +138 -0
  542. tomwer/utils.py +11 -39
  543. tomwer/version.py +3 -3
  544. {tomwer-1.3.27.dist-info → tomwer-1.4.0rc0.dist-info}/LICENSE +3 -3
  545. tomwer-1.4.0rc0.dist-info/METADATA +337 -0
  546. tomwer-1.4.0rc0.dist-info/RECORD +909 -0
  547. {tomwer-1.3.27.dist-info → tomwer-1.4.0rc0.dist-info}/WHEEL +1 -1
  548. {tomwer-1.3.27.dist-info → tomwer-1.4.0rc0.dist-info}/entry_points.txt +1 -0
  549. orangecontrib/tomwer/widgets/control/DataListOW.py +0 -129
  550. orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +0 -86
  551. orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +0 -182
  552. orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +0 -141
  553. orangecontrib/tomwer/widgets/icat/PublishProcessedDataOW.py +0 -115
  554. orangecontrib/tomwer/widgets/icat/RawDataScreenshotCreatorOW.py +0 -98
  555. orangecontrib/tomwer/widgets/icat/SaveToGalleryAndPublishOW.py +0 -129
  556. orangecontrib/tomwer/widgets/icat/icons/add_gallery.png +0 -0
  557. orangecontrib/tomwer/widgets/icat/icons/add_gallery.svg +0 -82
  558. orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.png +0 -0
  559. orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.svg +0 -143
  560. orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +0 -87
  561. orangecontrib/tomwer/widgets/visualization/icons/liveslice.png +0 -0
  562. orangecontrib/tomwer/widgets/visualization/icons/liveslice.svg +0 -110
  563. tomwer/core/log/logger.py +0 -130
  564. tomwer/core/process/control/test/test_volume_link.py +0 -74
  565. tomwer/core/process/control/tomoobjserie.py +0 -12
  566. tomwer/core/process/control/volumesymlink.py +0 -200
  567. tomwer/core/process/icat/createscreenshots.py +0 -100
  568. tomwer/core/process/icat/gallery.py +0 -377
  569. tomwer/core/process/icat/icatbase.py +0 -36
  570. tomwer/core/process/icat/publish.py +0 -228
  571. tomwer/core/process/icat/screenshots.py +0 -27
  572. tomwer/core/process/reconstruction/test/test_darkref.py +0 -60
  573. tomwer/core/process/reconstruction/test/test_sadeltabeta.py +0 -74
  574. tomwer/core/process/visualization/liveslice.py +0 -6
  575. tomwer/core/progress.py +0 -100
  576. tomwer/core/scan/test/test_edf.py +0 -53
  577. tomwer/core/scan/test/test_future_scan.py +0 -61
  578. tomwer/core/scan/test/test_h5.py +0 -96
  579. tomwer/core/test/test_scanutils.py +0 -53
  580. tomwer/gui/control/emailnotifier.py +0 -174
  581. tomwer/gui/control/serie/seriewaiter.py +0 -28
  582. tomwer/gui/control/test/__init__.py +0 -28
  583. tomwer/gui/control/test/test_datalist.py +0 -96
  584. tomwer/gui/control/test/test_datavalidator.py +0 -54
  585. tomwer/gui/control/test/test_email.py +0 -35
  586. tomwer/gui/control/test/test_process_manager.py +0 -65
  587. tomwer/gui/control/test/test_scanselector.py +0 -67
  588. tomwer/gui/edit/test/__init__.py +0 -28
  589. tomwer/gui/icat/gallery.py +0 -214
  590. tomwer/gui/icat/publish.py +0 -187
  591. tomwer/gui/reconstruction/axis/axis.py +0 -733
  592. tomwer/gui/reconstruction/axis/radioaxis.py +0 -2467
  593. tomwer/gui/stitching/stitching.py +0 -1388
  594. tomwer/gui/test/__init__.py +0 -28
  595. tomwer/gui/test/test_axis_gui.py +0 -34
  596. tomwer/synctools/stacks/edit/darkflatpatch.py +0 -169
  597. tomwer/synctools/stacks/edit/imagekeyeditor.py +0 -135
  598. tomwer/third_part/WaitingOverlay.py +0 -110
  599. tomwer-1.3.27-py3.11-nspkg.pth +0 -1
  600. tomwer-1.3.27.dist-info/METADATA +0 -292
  601. tomwer-1.3.27.dist-info/RECORD +0 -785
  602. tomwer-1.3.27.dist-info/namespace_packages.txt +0 -1
  603. /orangecontrib/tomwer/{widgets/edit/test → tests}/__init__.py +0 -0
  604. {tomwer/core/process/control/test → orangecontrib/tomwer/tutorials/id16b}/__init__.py +0 -0
  605. {tomwer/core/process/icat → orangecontrib/tomwer/widgets/cluster/tests}/__init__.py +0 -0
  606. /orangecontrib/tomwer/widgets/control/icons/{tomoobjserie.png → tomoobjseries.png} +0 -0
  607. {tomwer/core/process/reconstruction/test → orangecontrib/tomwer/widgets/control/tests}/__init__.py +0 -0
  608. /orangecontrib/tomwer/widgets/{icat → dataportal}/icons/publish_processed_data.png +0 -0
  609. /orangecontrib/tomwer/widgets/{icat → dataportal}/icons/publish_processed_data.svg +0 -0
  610. {tomwer/core/process/test → orangecontrib/tomwer/widgets/debugtools/tests}/__init__.py +0 -0
  611. {tomwer/core/scan/test → orangecontrib/tomwer/widgets/edit/tests}/__init__.py +0 -0
  612. {tomwer/core/test → orangecontrib/tomwer/widgets/other/tests}/__init__.py +0 -0
  613. {tomwer/gui/cluster/test → orangecontrib/tomwer/widgets/reconstruction/tests}/__init__.py +0 -0
  614. {tomwer/gui/control/serie → orangecontrib/tomwer/widgets/stitching/tests}/__init__.py +0 -0
  615. {tomwer/gui/icat → orangecontrib/tomwer/widgets/tests}/__init__.py +0 -0
  616. {tomwer/gui/reconstruction/test → orangecontrib/tomwer/widgets/visualization/tests}/__init__.py +0 -0
  617. /tomwer/{synctools/stacks/edit → app/stitching}/__init__.py +0 -0
  618. /tomwer/{synctools/test → core/process/control/tests}/__init__.py +0 -0
  619. /tomwer/core/process/control/{test → tests}/test_email.py +0 -0
  620. /tomwer/core/process/control/{test → tests}/test_h52nx_process.py +0 -0
  621. /tomwer/{third_part → core/process/drac}/__init__.py +0 -0
  622. /tomwer/core/process/reconstruction/{test → tests}/test_axis_params.py +0 -0
  623. /tomwer/core/process/reconstruction/{test → tests}/test_darkref_copy.py +0 -0
  624. /tomwer/core/process/reconstruction/{test → tests}/test_paramsbase.py +0 -0
  625. /tomwer/core/process/reconstruction/{test → tests}/test_utils.py +0 -0
  626. /tomwer/core/scan/{test → tests}/test_scan.py +0 -0
  627. /tomwer/gui/control/{serie → series}/nxtomoconcatenate.py +0 -0
  628. /tomwer/gui/control/{test → tests}/test_datadiscovery.py +0 -0
  629. /tomwer/gui/control/{test → tests}/test_reducedarkflat_selector.py +0 -0
  630. /tomwer/gui/control/{test → tests}/test_single_tomo_obj.py +0 -0
  631. {orangecontrib/tomwer/widgets/edit/test → tomwer/tests/orangecontrib/tomwer/widgets/edit/tests}/test_image_key_upgrader.py +0 -0
  632. {tomwer-1.3.27.dist-info → tomwer-1.4.0rc0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,491 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+
5
+ from silx.gui import qt
6
+
7
+ from tomwer.core.process.reconstruction.axis import mode as axis_mode
8
+ from tomwer.core.process.reconstruction.axis.anglemode import CorAngleMode
9
+ from tomwer.core.process.reconstruction.axis.params import (
10
+ DEFAULT_CMP_N_SUBSAMPLING_Y,
11
+ DEFAULT_CMP_OVERSAMPLING,
12
+ DEFAULT_CMP_TAKE_LOG,
13
+ DEFAULT_CMP_THETA,
14
+ )
15
+ from tomwer.gui.utils.scrollarea import QComboBoxIgnoreWheel
16
+ from tomwer.core.scan.scanbase import TomwerScanBase
17
+ from tomwer.gui.utils.qt_utils import block_signals
18
+ from tomwer.synctools.axis import QAxisRP
19
+ from .CalculationWidget import CalculationWidget
20
+ from .ManualFramesSelection import ManualFramesSelection
21
+
22
+ _logger = logging.getLogger(__name__)
23
+
24
+
25
+ class InputWidget(qt.QWidget):
26
+ """
27
+ Widget used to define the radios or the sinogram to be used for computing the cor
28
+ Used as a tab of the AxisSettingsTabWidget
29
+ """
30
+
31
+ sigChanged = qt.Signal()
32
+ """Signal emitted when input changed"""
33
+
34
+ _sigUrlChanged = qt.Signal()
35
+ """Signal emit when url to be used changed"""
36
+
37
+ def __init__(self, parent=None, axis_params=None):
38
+ assert isinstance(axis_params, QAxisRP)
39
+ self._blockUpdateAxisParams = False
40
+ super().__init__(parent)
41
+ self.setLayout(qt.QVBoxLayout())
42
+
43
+ # radio input
44
+ self._radioGB = qt.QGroupBox(self)
45
+ self._radioGB.setTitle("radios")
46
+ self._radioGB.setLayout(qt.QVBoxLayout())
47
+ self._radioGB.setCheckable(True)
48
+ self.layout().addWidget(self._radioGB)
49
+ ## angle mode
50
+ self._angleModeWidget = _AngleSelectionWidget(
51
+ parent=self, axis_params=axis_params
52
+ )
53
+ self._radioGB.layout().addWidget(self._angleModeWidget)
54
+ self._axis_params = axis_params
55
+
56
+ # sinogram input
57
+ self._sinogramGB = qt.QGroupBox(self)
58
+ self._sinogramGB.setLayout(qt.QVBoxLayout())
59
+ self._standardSinogramOpts = qt.QGroupBox(self)
60
+ self._sinogramGB.layout().addWidget(self._standardSinogramOpts)
61
+ self._standardSinogramOpts.setLayout(qt.QFormLayout())
62
+ self._standardSinogramOpts.layout().setContentsMargins(0, 0, 0, 0)
63
+ self._standardSinogramOpts.setTitle("standard options")
64
+
65
+ self._sinogramGB.setTitle("sinogram")
66
+ self._sinogramGB.setCheckable(True)
67
+ self.layout().addWidget(self._sinogramGB)
68
+ ## sinogram line
69
+ self._sinogramLineSB = _SliceSelector(self)
70
+ self._standardSinogramOpts.layout().addRow("line", self._sinogramLineSB)
71
+ ## sinogram subsampling
72
+ self._sinogramSubsampling = qt.QSpinBox(self)
73
+ self._sinogramSubsampling.setRange(1, 1000)
74
+ self._sinogramSubsampling.setValue(10)
75
+ self._standardSinogramOpts.layout().addRow(
76
+ "subsampling", self._sinogramSubsampling
77
+ )
78
+
79
+ self._spacer = qt.QWidget(self)
80
+ self._spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
81
+ self.layout().addWidget(self._spacer)
82
+
83
+ ## options for the composite mode
84
+ self._compositeOpts = qt.QGroupBox(self)
85
+ self._compositeOpts.setTitle("composite options")
86
+ self._sinogramGB.layout().addWidget(self._compositeOpts)
87
+ self._compositeOpts.setLayout(qt.QFormLayout())
88
+ self._compositeOpts.layout().setContentsMargins(0, 0, 0, 0)
89
+ self._thetaSB = qt.QSpinBox(self)
90
+ self._thetaSB.setRange(0, 360)
91
+ self._thetaSB.setValue(DEFAULT_CMP_THETA)
92
+ self._thetaSB.setToolTip("a radio will be picked each theta degres")
93
+ self._thetaLabel = qt.QLabel("angle interval (in degree)", self)
94
+ self._thetaLabel.setToolTip(
95
+ "algorithm will take one projection each 'angle interval'. Also know as 'theta'"
96
+ )
97
+ self._compositeOpts.layout().addRow(self._thetaLabel, self._thetaSB)
98
+
99
+ self._oversamplingSB = qt.QSpinBox(self)
100
+ self._oversamplingSB.setValue(DEFAULT_CMP_OVERSAMPLING)
101
+ self._oversamplingSB.setToolTip("sinogram oversampling")
102
+ self._compositeOpts.layout().addRow("oversampling", self._oversamplingSB)
103
+
104
+ self._nearwidthSB = qt.QSpinBox(self)
105
+ self._nearwidthSB.setRange(-40000, 40000)
106
+ self._nearwidthSB.setValue(0)
107
+ self._nearwidthSB.setToolTip("position to be used with near option")
108
+ self._nearwidthLabel = qt.QLabel("near width", self)
109
+ self._nearwidthLabel.setToolTip("position to be used with near option")
110
+ self._compositeOpts.layout().addRow(self._nearwidthLabel, self._nearwidthSB)
111
+
112
+ self._subsamplingYSB = qt.QSpinBox(self)
113
+ self._subsamplingYSB.setValue(DEFAULT_CMP_N_SUBSAMPLING_Y)
114
+ self._subsamplingYSB.setToolTip("sinogram number of subsampling along y")
115
+ self._compositeOpts.layout().addRow("n_subsampling_y", self._subsamplingYSB)
116
+
117
+ self._takeLogCB = qt.QCheckBox(self)
118
+ self._takeLogCB.setToolTip("Take logarithm")
119
+ self._takeLogCB.setChecked(DEFAULT_CMP_TAKE_LOG)
120
+ self._takeTheLogLabel = qt.QLabel("linearisation (-log(I/I0))")
121
+ self._takeTheLogLabel.setToolTip(
122
+ "take (-log(I/I0)) as input. Also know as 'take_log' option"
123
+ )
124
+ self._compositeOpts.layout().addRow(self._takeTheLogLabel, self._takeLogCB)
125
+
126
+ # set up
127
+ self._sinogramGB.setChecked(False)
128
+
129
+ # connect signal / slot
130
+ self._sinogramGB.toggled.connect(self._sinogramChecked)
131
+ self._radioGB.toggled.connect(self._radiosChecked)
132
+ self._sinogramSubsampling.valueChanged.connect(self._changed)
133
+ self._sinogramLineSB.sigChanged.connect(self._changed)
134
+ self._thetaSB.valueChanged.connect(self._changed)
135
+ self._oversamplingSB.valueChanged.connect(self._changed)
136
+ self._subsamplingYSB.valueChanged.connect(self._changed)
137
+ self._nearwidthSB.valueChanged.connect(self._changed)
138
+ self._takeLogCB.toggled.connect(self._changed)
139
+ self._angleModeWidget.sigChanged.connect(self._sigUrlChanged)
140
+
141
+ def setScan(self, scan: TomwerScanBase):
142
+ if scan is not None:
143
+ self._angleModeWidget.setScan(scan)
144
+ self._angleModeWidget.setScanRange(scan.scan_range)
145
+
146
+ def setAxisParams(self, axis_params):
147
+ with block_signals(axis_params):
148
+ with block_signals(self._axis_params):
149
+ self._blockUpdateAxisParams = True
150
+
151
+ if axis_params is not None:
152
+ assert isinstance(axis_params, QAxisRP)
153
+ with block_signals(self._sinogramGB):
154
+ self._sinogramChecked(axis_params.use_sinogram, on_load=True)
155
+ self._sinogramLineSB.setSlice(axis_params.sinogram_line)
156
+ self._sinogramSubsampling.setValue(axis_params.sinogram_subsampling)
157
+ self.setCompositeOptions(axis_params.composite_options)
158
+ self._angleModeWidget.setAxisParams(axis_params)
159
+ self._axis_params = axis_params
160
+
161
+ self._blockUpdateAxisParams = False
162
+
163
+ def getSinogramLine(self) -> str | int:
164
+ return self._sinogramLineSB.getSlice()
165
+
166
+ def getSinogramSubsampling(self) -> int:
167
+ return self._sinogramSubsampling.value()
168
+
169
+ def _sinogramChecked(self, checked, on_load=False):
170
+ with block_signals(self._radioGB):
171
+ with block_signals(self._sinogramGB):
172
+ if checked:
173
+ self._radioGB.setChecked(False)
174
+ self._sinogramGB.setChecked(True)
175
+ elif self._radioGB.isEnabled():
176
+ self._radioGB.setChecked(not checked)
177
+ elif on_load:
178
+ self._sinogramGB.setChecked(checked)
179
+ else:
180
+ # ignore it if radio disabled
181
+ self._sinogramGB.setChecked(True)
182
+ self._changed()
183
+
184
+ def _radiosChecked(self, checked, on_load=False):
185
+ with block_signals(self._radioGB):
186
+ with block_signals(self._sinogramGB):
187
+ if checked:
188
+ self._sinogramGB.setChecked(False)
189
+ self._radioGB.setChecked(True)
190
+ elif self._sinogramGB.isEnabled():
191
+ self._sinogramGB.setChecked(not checked)
192
+ elif on_load:
193
+ self._radioGB.setChecked(checked)
194
+ else:
195
+ # ignore it if sinogram disabled
196
+ self._radioGB.setChecked(True)
197
+ self._changed()
198
+
199
+ def _changed(self, *args, **kwargs):
200
+ self._updateAxisParams()
201
+ self.sigChanged.emit()
202
+
203
+ def _updateAxisParams(self):
204
+ if not self._blockUpdateAxisParams:
205
+ self._axis_params.use_sinogram = self._sinogramGB.isChecked()
206
+ self._axis_params.sinogram_line = self.getSinogramLine()
207
+ self._axis_params.sinogram_subsampling = self.getSinogramSubsampling()
208
+ self._axis_params.composite_options = self.getCompositeOptions()
209
+
210
+ def setValidInputs(self, modes: list | tuple):
211
+ """
212
+ Define possible inputs.
213
+
214
+ :raises: ValueError if modes are invalid
215
+ """
216
+ modes = set(modes)
217
+ for mode in modes:
218
+ try:
219
+ axis_mode._InputType.from_value(mode)
220
+ except Exception:
221
+ raise ValueError(
222
+ f"mode {mode} should be an instance of {axis_mode._InputType}"
223
+ )
224
+ if len(modes) == 2:
225
+ self._sinogramGB.setEnabled(True)
226
+ self._radioGB.setEnabled(True)
227
+ elif len(modes) > 2:
228
+ raise ValueError(f"invalid input {modes}")
229
+ elif len(modes) < 0:
230
+ raise ValueError("modes is empty")
231
+ else:
232
+ mode = axis_mode._InputType.from_value(modes.pop())
233
+ if mode in (axis_mode._InputType.SINOGRAM, axis_mode._InputType.COMPOSITE):
234
+ self._sinogramGB.setEnabled(True)
235
+ self._radioGB.setEnabled(False)
236
+ self._sinogramGB.setChecked(True)
237
+ self._compositeOpts.setEnabled(mode is axis_mode._InputType.COMPOSITE)
238
+ self._standardSinogramOpts.setEnabled(
239
+ mode is not axis_mode._InputType.COMPOSITE
240
+ )
241
+ elif mode is axis_mode._InputType.RADIOS_X2:
242
+ self._radioGB.setEnabled(True)
243
+ self._sinogramGB.setEnabled(False)
244
+ self._radioGB.setChecked(True)
245
+ else:
246
+ raise ValueError(f"Nothing implemented for {mode.value}")
247
+
248
+ def getCompositeOptions(self) -> dict:
249
+ return {
250
+ "theta": self.getTheta(),
251
+ "oversampling": self.getOversampling(),
252
+ "n_subsampling_y": self.getSubsamplingY(),
253
+ "take_log": self.getTakeLog(),
254
+ "near_pos": self.getNearpos(),
255
+ "near_width": self.getNearwidth(),
256
+ }
257
+
258
+ def setCompositeOptions(self, opts: dict) -> None:
259
+ if not isinstance(opts, dict):
260
+ raise TypeError("opts should be an instance of dict")
261
+ for key in opts.keys():
262
+ if key not in (
263
+ "theta",
264
+ "oversampling",
265
+ "n_subsampling_y",
266
+ "take_log",
267
+ "near_pos",
268
+ "near_width",
269
+ ):
270
+ raise KeyError(f"{key} is not recogized")
271
+ theta = opts.get("theta", None)
272
+ if theta is not None:
273
+ self.setTheta(theta=theta)
274
+ oversampling = opts.get("oversampling", None)
275
+ if oversampling is not None:
276
+ self.setOversampling(oversampling)
277
+ n_subsampling_y = opts.get("n_subsampling_y", None)
278
+ if n_subsampling_y is not None:
279
+ self.setSubsamplingY(n_subsampling_y)
280
+
281
+ near_width = opts.get("near_width", None)
282
+ if near_width is not None:
283
+ self.setNearwidth(near_width)
284
+
285
+ take_log = opts.get("take_log", None)
286
+ if take_log is not None:
287
+ self.setTakeLog(take_log)
288
+
289
+ def getTheta(self) -> int:
290
+ return self._thetaSB.value()
291
+
292
+ def setTheta(self, theta: int) -> None:
293
+ self._thetaSB.setValue(theta)
294
+
295
+ def getOversampling(self) -> int:
296
+ return self._oversamplingSB.value()
297
+
298
+ def setOversampling(self, oversampling: int) -> None:
299
+ self._oversamplingSB.setValue(oversampling)
300
+
301
+ def getNearpos(self) -> int:
302
+ cal_widget = self.parentWidget().widget(0)
303
+ assert isinstance(cal_widget, CalculationWidget)
304
+ return cal_widget.getEstimatedCor()
305
+
306
+ def setNearpos(self, value) -> int:
307
+ cal_widget = self.parentWidget().widget(0)
308
+ assert isinstance(cal_widget, CalculationWidget)
309
+ cal_widget.setNearPosition(value)
310
+
311
+ def getNearwidth(self) -> int:
312
+ return self._nearwidthSB.value()
313
+
314
+ def setNearwidth(self, value) -> int:
315
+ return self._nearwidthSB.setValue(value)
316
+
317
+ def getSubsamplingY(self) -> int:
318
+ return self._subsamplingYSB.value()
319
+
320
+ def setSubsamplingY(self, subsampling: int) -> None:
321
+ self._subsamplingYSB.setValue(subsampling)
322
+
323
+ def getTakeLog(self) -> bool:
324
+ return self._takeLogCB.isChecked()
325
+
326
+ def setTakeLog(self, log: bool) -> None:
327
+ self._takeLogCB.setChecked(log)
328
+
329
+
330
+ class _AngleSelectionWidget(qt.QWidget):
331
+ """Group box to select the angle to used for cor calculation
332
+ (0-180, 90-270 or manual)"""
333
+
334
+ sigChanged = qt.Signal()
335
+ """signal emitted when the selected angle changed"""
336
+
337
+ def __init__(self, parent=None, axis_params=None):
338
+ assert isinstance(axis_params, QAxisRP)
339
+ qt.QWidget.__init__(
340
+ self,
341
+ parent=parent,
342
+ )
343
+ self.setLayout(qt.QVBoxLayout())
344
+ self._groupBoxMode = qt.QGroupBox(
345
+ self, title="Angles to use for axis calculation"
346
+ )
347
+ self._groupBoxMode.setLayout(qt.QHBoxLayout())
348
+ self.layout().addWidget(self._groupBoxMode)
349
+
350
+ self._corButtonsGps = qt.QButtonGroup(parent=self)
351
+ self._corButtonsGps.setExclusive(True)
352
+ self._qrbCOR_0_180 = qt.QRadioButton("0-180", parent=self)
353
+ self._groupBoxMode.layout().addWidget(self._qrbCOR_0_180)
354
+ self._qrbCOR_90_270 = qt.QRadioButton("90-270", parent=self)
355
+ self._qrbCOR_90_270.setToolTip(
356
+ "pick radio closest to angles 90° and "
357
+ "270°. If disable mean that the scan "
358
+ "range is 180°"
359
+ )
360
+ self._groupBoxMode.layout().addWidget(self._qrbCOR_90_270)
361
+ self._qrbCOR_manual = qt.QRadioButton("other", parent=self)
362
+ self._qrbCOR_manual.setVisible(True)
363
+ self._groupBoxMode.layout().addWidget(self._qrbCOR_manual)
364
+ # add all button to the button group
365
+ for b in (self._qrbCOR_0_180, self._qrbCOR_90_270, self._qrbCOR_manual):
366
+ self._corButtonsGps.addButton(b)
367
+
368
+ self.setAxisParams(axis_params)
369
+
370
+ self._manualFrameSelection = ManualFramesSelection(self)
371
+ self.layout().addWidget(self._manualFrameSelection)
372
+ self._manualFrameSelection.setVisible(False)
373
+
374
+ # connect signal / Slot
375
+ self._corButtonsGps.buttonClicked.connect(self._angleModeChanged)
376
+ self._manualFrameSelection.sigChanged.connect(self._changed)
377
+
378
+ def setScan(self, scan: TomwerScanBase):
379
+ if scan is not None:
380
+ self.setScanRange(scan.scan_range)
381
+ self._manualFrameSelection.setScan(scan=scan)
382
+
383
+ def setScanRange(self, scanRange):
384
+ if scanRange == 180:
385
+ self._qrbCOR_90_270.setEnabled(False)
386
+ # force using 0-180 if was using 90-270
387
+ if self._qrbCOR_90_270.isChecked():
388
+ self._qrbCOR_0_180.setChecked(True)
389
+ self._axis_params.angle_mode = CorAngleMode.use_0_180
390
+ else:
391
+ self._qrbCOR_90_270.setEnabled(True)
392
+
393
+ def setAngleMode(self, mode):
394
+ """
395
+
396
+ :param mode: mode to use (can be manual , 90-270 or 0-180)
397
+ """
398
+ assert isinstance(mode, CorAngleMode)
399
+ if mode == CorAngleMode.use_0_180:
400
+ self._qrbCOR_0_180.setChecked(True)
401
+ elif mode == CorAngleMode.use_90_270:
402
+ self._qrbCOR_90_270.setChecked(True)
403
+ else:
404
+ self._qrbCOR_manual.setChecked(True)
405
+
406
+ def getAngleMode(self) -> CorAngleMode:
407
+ """
408
+
409
+ :return: the angle to use for the axis calculation
410
+ """
411
+ if self._qrbCOR_90_270.isChecked():
412
+ return CorAngleMode.use_90_270
413
+ elif self._qrbCOR_0_180.isChecked():
414
+ return CorAngleMode.use_0_180
415
+ else:
416
+ return CorAngleMode.manual_selection
417
+
418
+ def setAxisParams(self, axis_params):
419
+ with block_signals(self):
420
+ self._axis_params = axis_params
421
+ # set up
422
+ self.setAngleMode(axis_params.angle_mode)
423
+
424
+ def _angleModeChanged(self, *args, **kwargs):
425
+ self._axis_params.angle_mode = self.getAngleMode()
426
+ if self.getAngleMode() is CorAngleMode.manual_selection:
427
+ self._axis_params.angle_mode_extra = (
428
+ self._manualFrameSelection.getFramesUrl()
429
+ )
430
+ else:
431
+ self._axis_params.angle_mode_extra = None
432
+ self._manualFrameSelection.setVisible(
433
+ self.getAngleMode() is CorAngleMode.manual_selection
434
+ )
435
+ self._changed()
436
+
437
+ def _changed(self):
438
+ self.sigChanged.emit()
439
+
440
+
441
+ class _SliceSelector(qt.QWidget):
442
+ sigChanged = qt.Signal()
443
+ """signal emit when the selected slice change"""
444
+
445
+ def __init__(self, parent):
446
+ qt.QWidget.__init__(self, parent)
447
+ self.setLayout(qt.QHBoxLayout())
448
+ self.setContentsMargins(0, 0, 0, 0)
449
+ self.layout().setContentsMargins(0, 0, 0, 0)
450
+ self._modeCB = QComboBoxIgnoreWheel(self)
451
+ self._modeCB.addItem("middle")
452
+ self._modeCB.addItem("other")
453
+ self.layout().addWidget(self._modeCB)
454
+ self._otherSB = qt.QSpinBox(self)
455
+ self._otherSB.setRange(0, 10000)
456
+ self.layout().addWidget(self._otherSB)
457
+
458
+ # connect signal / slot
459
+ self._otherSB.valueChanged.connect(self._valueChanged)
460
+ self._modeCB.currentIndexChanged.connect(self._modeChanged)
461
+ # set up
462
+ self._modeChanged()
463
+
464
+ def getSlice(self) -> int | str:
465
+ "return a specific slice index or 'middle'"
466
+ if self.getMode() == "middle":
467
+ return "middle"
468
+ else:
469
+ return self._otherSB.value()
470
+
471
+ def setSlice(self, slice_):
472
+ if slice_ is None:
473
+ return
474
+ if slice_ == "middle":
475
+ idx = self._modeCB.findText("middle")
476
+ self._modeCB.setCurrentIndex(idx)
477
+ else:
478
+ idx = self._modeCB.findText("other")
479
+ self._modeCB.setCurrentIndex(idx)
480
+ self._otherSB.setValue(slice_)
481
+ self.sigChanged.emit()
482
+
483
+ def getMode(self):
484
+ return self._modeCB.currentText()
485
+
486
+ def _valueChanged(self):
487
+ self.sigChanged.emit()
488
+
489
+ def _modeChanged(self, *args, **kwargs):
490
+ self._otherSB.setVisible(self.getMode() == "other")
491
+ self._valueChanged()
@@ -0,0 +1,168 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from bisect import bisect_left
5
+
6
+ from silx.gui import qt
7
+ from silx.io.url import DataUrl
8
+
9
+ from tomwer.core.scan.scanbase import TomwerScanBase
10
+
11
+ _logger = logging.getLogger(__name__)
12
+
13
+
14
+ class ManualFramesSelection(qt.QWidget):
15
+ """Allows to select frame - angle to be used."""
16
+
17
+ sigChanged = qt.Signal()
18
+ """Signal emit when the frame selection changes"""
19
+
20
+ def __init__(self, parent=None) -> None:
21
+ super().__init__(parent)
22
+ self._anglesAvailable = []
23
+ # cache of the angles available from the current defined frames. Must be sorted !!!
24
+ self.setLayout(qt.QGridLayout())
25
+ self.layout().addWidget(qt.QLabel("frame 1", self), 0, 0, 1, 1)
26
+ self._frame1CB = qt.QComboBox(self)
27
+ self._frame1CB.setEditable(True)
28
+ self.layout().addWidget(self._frame1CB, 0, 1, 1, 1)
29
+
30
+ self.layout().addWidget(qt.QLabel("frame 2", self), 1, 0, 1, 1)
31
+ self._frame2CB = qt.QComboBox(self)
32
+ self._frame2CB.setEditable(True)
33
+ self.layout().addWidget(self._frame2CB, 1, 1, 1, 1)
34
+ self._findAssociatedAnglePB = qt.QPushButton("+180°", self)
35
+ button_180_font = self.font()
36
+ button_180_font.setPixelSize(10)
37
+ self._findAssociatedAnglePB.setFont(button_180_font)
38
+ self._findAssociatedAnglePB.setFixedWidth(30)
39
+ self._findAssociatedAnglePB.setSizePolicy(
40
+ qt.QSizePolicy.Minimum, qt.QSizePolicy.Minimum
41
+ )
42
+ self.layout().addWidget(self._findAssociatedAnglePB, 1, 2, 1, 1)
43
+ self._flipLRCB = qt.QCheckBox("flip L-R")
44
+ self._flipLRCB.setChecked(True)
45
+ self.layout().addWidget(self._flipLRCB, 1, 3, 1, 1)
46
+
47
+ self._flipLRCB.toggled.connect(self._changed)
48
+ self._frame1CB.currentIndexChanged.connect(self._changed)
49
+ self._frame2CB.currentIndexChanged.connect(self._changed)
50
+ self._findAssociatedAnglePB.released.connect(self._findAssociatedAngle)
51
+
52
+ def _findAssociatedAngle(self):
53
+ if self._frame1CB.count() == 0 or len(self._anglesAvailable) == 0:
54
+ _logger.warning("no angles available, unable to get '+180°' frame")
55
+ else:
56
+ angle = float(self._frame1CB.currentText())
57
+ # look for the closest 'associated' angle.
58
+ # as the angles are not limited to [0-360] we need to check for any value.
59
+ # if the angle is on the first part of the acquisition we expect to find it near angle +180
60
+ # if it is on the second part (for 360 degree) we expect to find it on the first part (0-180)
61
+ closest_pls_180_angle = self._getClosestAssociatedAngle(
62
+ angle + 180.0, self._anglesAvailable
63
+ )
64
+ score_add = abs(closest_pls_180_angle - angle)
65
+ closest_minus_180_angle = self._getClosestAssociatedAngle(
66
+ angle - 180.0, self._anglesAvailable
67
+ )
68
+ score_sub = abs(closest_minus_180_angle - angle)
69
+ if score_add >= score_sub:
70
+ closest_180_angle = closest_pls_180_angle
71
+ else:
72
+ closest_180_angle = closest_minus_180_angle
73
+ item_idx = self._frame2CB.findText(self._angleToStr(closest_180_angle))
74
+ if item_idx < 0:
75
+ _logger.error(f"Unable to find item for angle {closest_180_angle}")
76
+ else:
77
+ self._frame2CB.setCurrentIndex(item_idx)
78
+
79
+ @staticmethod
80
+ def _getClosestAssociatedAngle(angle: float, angles: tuple) -> float:
81
+ """
82
+ return the angle closest angle to 'angle' from 'angles'
83
+
84
+ :warning: angles should be already sorted !!!
85
+ """
86
+ if angles is None or len(angles) == 0:
87
+ return None
88
+ if angle in angles:
89
+ return angle
90
+ pos = bisect_left(angles, angle)
91
+ if pos == 0:
92
+ return angles[0]
93
+ elif pos > len(angles) - 1:
94
+ return angles[-1]
95
+ else:
96
+ left_angle = angles[pos - 1]
97
+ right_angle = angles[pos]
98
+ if abs(right_angle - angle) > abs(left_angle - angle):
99
+ return left_angle
100
+ else:
101
+ return right_angle
102
+
103
+ def _changed(self):
104
+ self.sigChanged.emit()
105
+
106
+ @staticmethod
107
+ def _angleToStr(angle: float) -> str:
108
+ return f"{float(angle):0.3f}"
109
+
110
+ def setScan(self, scan: TomwerScanBase | None) -> None:
111
+ self._anglesAvailable.clear()
112
+ self._frame1CB.clear()
113
+ self._frame2CB.clear()
114
+ if scan is None:
115
+ return
116
+ current_angle1 = self._getFrame1Angle()
117
+ current_angle2 = self._getFrame2Angle()
118
+ for proj_angle, proj_url in scan.get_proj_angle_url().items():
119
+ try:
120
+ angle = self._angleToStr(proj_angle)
121
+ except Exception:
122
+ angle = proj_angle
123
+ else:
124
+ self._anglesAvailable.append(float(proj_angle))
125
+ self._frame1CB.addItem(angle, proj_url)
126
+ self._frame2CB.addItem(angle, proj_url)
127
+
128
+ self._anglesAvailable.sort()
129
+
130
+ idx = self._frame1CB.findText(current_angle1)
131
+ if idx >= 0:
132
+ self._frame1CB.setCurrentIndex(idx)
133
+ if current_angle1 == current_angle2:
134
+ # if the two current angle are close then we consider it is better to look for angleX - angleX + 180 angles
135
+ # instead of finding back angles
136
+ self._findAssociatedAngle()
137
+ else:
138
+ idx = self._frame1CB.findText(current_angle1)
139
+ if idx >= 0:
140
+ self._frame1CB.setCurrentIndex(idx)
141
+
142
+ idx = self._frame2CB.findText(current_angle2)
143
+ if idx >= 0:
144
+ self._frame2CB.setCurrentIndex(idx)
145
+
146
+ def getFramesUrl(self, as_txt=False) -> tuple:
147
+ """
148
+ Return a tuple of (frame 1 url, frame 2 url). Url can be None
149
+ """
150
+ if as_txt:
151
+ return self.getFrame1Url().path(), self.getFrame2Url().path()
152
+ else:
153
+ return self.getFrame1Url(), self.getFrame2Url()
154
+
155
+ def getFrame1Url(self) -> DataUrl | None:
156
+ return self._frame1CB.currentData()
157
+
158
+ def getFrame2Url(self) -> DataUrl | None:
159
+ return self._frame2CB.currentData()
160
+
161
+ def _getFrame1Angle(self) -> str | None:
162
+ return self._frame1CB.currentText()
163
+
164
+ def _getFrame2Angle(self) -> str | None:
165
+ return self._frame2CB.currentText()
166
+
167
+ def isFrame2LRFLip(self):
168
+ return self._flipLRCB.isChecked()
@@ -1,2 +1,2 @@
1
- from .axis import AxisWindow # noqa F401
2
- from .radioaxis import RadioAxisWindow # noqa F401
1
+ from .AxisMainWindow import AxisMainWindow # noqa F401
2
+ from .AxisWidget import AxisWidget # noqa F401
@@ -1,27 +0,0 @@
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
- __authors__ = ["H. Payno"]
26
- __license__ = "MIT"
27
- __date__ = "09/02/2018"