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
@@ -1,896 +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
-
26
- __authors__ = ["H. Payno"]
27
- __license__ = "MIT"
28
- __date__ = "01/06/2018"
29
-
30
-
31
- import logging
32
- import os
33
-
34
- from silx.gui import qt
35
-
36
- from tomwer.core.process.reconstruction.lamino.tofu import FFCWhen, getDark, getFlats
37
- from tomwer.core.utils import (
38
- getClosestEnergy,
39
- getDARK_N,
40
- getDim1Dim2,
41
- getParametersFromParOrInfo,
42
- getPixelSize,
43
- getTomo_N,
44
- )
45
- from tomwer.core.utils.char import PSI_CHAR, THETA_CHAR
46
- from tomwer.gui import icons
47
- from tomwer.gui.utils.illustrations import _IllustrationDialog, _IllustrationWidget
48
- from tomwer.gui.utils.unitsystem import MetricEntry
49
-
50
- from .misc import PadlockButton, _AngleWidget
51
- from .TofuOptionLoader import _getterSetter, _TofuOptionLoader
52
-
53
- _logger = logging.getLogger(__name__)
54
-
55
-
56
- class InputProjectionsScrollArea(qt.QScrollArea):
57
- def __init__(self, parent):
58
- qt.QScrollArea.__init__(self, parent)
59
- self.widget = InputProjectionsWidget(parent=self)
60
- self.setWidget(self.widget)
61
- self.setWidgetResizable(True)
62
-
63
- # expose API
64
- self.loadFromScan = self.widget.loadFromScan
65
- self.setNumber = self.widget.setNumber
66
- self.getNumber = self.widget.getNumber
67
- self.getPixelSize = self.widget.getPixelSize
68
- self.setPixelSize = self.widget.setPixelSize
69
- self.pixelSizeIsLocked = self.widget.pixelSizeIsLocked
70
- self.getParameters = self.widget.getParameters
71
- self.loadFromScan = self.widget.loadFromScan
72
- self.setParameters = self.widget.setParameters
73
- self.rotationAngle = self.widget.rotationAngle
74
- self.centeringWidget = self.widget.centeringWidget
75
- self.getWhenApplyFFC = self.widget.getWhenApplyFFC
76
- self.setWhenApplyFFC = self.widget.setWhenApplyFFC
77
- self.isHalfAcquisition = self.widget.isHalfAcquisition
78
- self.setHalfAcquisition = self.widget.setHalfAcquisition
79
- self.setBlend = self.widget.setBlend
80
- self.setAdjustMean = self.widget.setAdjustMean
81
-
82
-
83
- class InputProjectionsWidget(_TofuOptionLoader, qt.QWidget):
84
- """TabWidget containing all the information relative to the
85
- flat field correction"""
86
-
87
- def __init__(self, parent):
88
- qt.QWidget.__init__(self, parent)
89
- self.setLayout(qt.QGridLayout())
90
-
91
- self.rotationAngle = RotationAngleGroupBox(parent=self)
92
- self.layout().addWidget(self.rotationAngle, 0, 0)
93
-
94
- self.centeringWidget = CenteringTofuGroupBox(parent=self)
95
- self.layout().addWidget(self.centeringWidget, 1, 0)
96
-
97
- self._numberOfFiles = NbFilesWidget(parent=self)
98
- self._numberOfFiles.layout().setContentsMargins(6, 2, 2, 2)
99
- self.layout().addWidget(self._numberOfFiles, 2, 0)
100
-
101
- # pixel size
102
- self._pixelWidget = qt.QWidget(parent=self)
103
- self._pixelWidget.setLayout(qt.QHBoxLayout())
104
- self._pixelWidget.layout().setContentsMargins(6, 2, 2, 2)
105
-
106
- self._pixelSize = MetricEntry(name="pixel size", parent=self, default_unit="m")
107
- self._pixelWidget.layout().addWidget(self._pixelSize._label)
108
- self._pixelWidget.layout().addWidget(self._pixelSize._qlePixelSize)
109
- self._pixelWidget.layout().addWidget(self._pixelSize._qcbUnit)
110
- self._pixelSizeLockButton = PadlockButton(parent=self)
111
- self._pixelWidget.layout().addWidget(self._pixelSizeLockButton)
112
- self.layout().addWidget(self._pixelWidget, 3, 0)
113
-
114
- # half & options
115
- self._halfAcqWidget = qt.QWidget(parent=self)
116
- self._halfAcqWidget.setLayout(qt.QHBoxLayout())
117
- self._halfAcqWidget.layout().setContentsMargins(6, 2, 2, 2)
118
- self._halfAcqCB = qt.QCheckBox("half acquisition", parent=self)
119
- self._halfAcqWidget.layout().addWidget(self._halfAcqCB)
120
- self._blendCB = qt.QCheckBox("blend", parent=self)
121
- self._blendCB.setVisible(False)
122
- self._halfAcqWidget.layout().addWidget(self._blendCB)
123
- self._adjustMeanCB = qt.QCheckBox("adjust mean", parent=self)
124
- self._adjustMeanCB.setVisible(False)
125
- self._halfAcqWidget.layout().addWidget(self._adjustMeanCB)
126
- self.layout().addWidget(self._halfAcqWidget, 4, 0)
127
-
128
- # flat field correction
129
- self._ffcWidget = _FFCConfigWidget(parent=self)
130
- self.layout().addWidget(self._ffcWidget, 5, 0, 2, 2)
131
-
132
- self._phaseRetrieval = PhaseRetrievalWidget(parent=self)
133
- self._phaseRetrieval.setCheckable(True)
134
- self._phaseRetrieval.setChecked(False)
135
- self.layout().addWidget(self._phaseRetrieval, 7, 0)
136
-
137
- spacer = qt.QWidget(self)
138
- spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
139
- self.layout().addWidget(spacer)
140
-
141
- self._ffcWidget._absortivityActivated.connect(self._phaseRetrieval.setUnchecked)
142
- self._phaseRetrieval.activated.connect(self._ffcWidget.uncheckedAbsorptivity)
143
-
144
- # expose API
145
- self.setNumber = self._numberOfFiles.setNumberOfFiles
146
- self.getNumber = self._numberOfFiles.getNumberOfFiles
147
- self.getPixelSize = self._pixelSize.getValue
148
- self.setPixelSize = self._pixelSize.setValue
149
- self.pixelSizeIsLocked = self._pixelSizeLockButton.isLocked
150
- self.getWhenApplyFFC = self._ffcWidget.getWhenApplyFFC
151
- self.setWhenApplyFFC = self._ffcWidget.setWhenApplyFFC
152
- self.isHalfAcquisition = self._halfAcqCB.isChecked
153
- self.setHalfAcquisition = self._halfAcqCB.setChecked
154
- self.isBlend = self._blendCB.isChecked
155
- self.setBlend = self._blendCB.setChecked
156
- self.isAdjustMean = self._adjustMeanCB.isChecked
157
- self.setAdjustMean = self._adjustMeanCB.setChecked
158
-
159
- options = {
160
- "ffc-when": _getterSetter(
161
- getter=self.getWhenApplyFFC, setter=self.setWhenApplyFFC
162
- ),
163
- "number": _getterSetter(getter=self.getNumber, setter=self.setNumber),
164
- "reduction-mode": _getterSetter(
165
- getter=self._ffcWidget.getMethod, setter=self._ffcWidget.setMethod
166
- ),
167
- "darks": _getterSetter(
168
- getter=self._ffcWidget.getDarks, setter=self._ffcWidget.setDarks
169
- ),
170
- "flats": _getterSetter(
171
- getter=self._ffcWidget.getFlats, setter=self._ffcWidget.setFlats
172
- ),
173
- "flats2": _getterSetter(
174
- getter=self._ffcWidget.getSecondFlats,
175
- setter=self._ffcWidget.setSecondFlats,
176
- ),
177
- "absorptivity": _getterSetter(
178
- getter=self._ffcWidget.requireAbsorptivity,
179
- setter=self._ffcWidget.setAbsortivity,
180
- ),
181
- "fix-nan-and-inf": _getterSetter(
182
- getter=self._ffcWidget.removeNanAndInf,
183
- setter=self._ffcWidget.setNanAndInf,
184
- ),
185
- "dark-scale": _getterSetter(
186
- getter=self._ffcWidget.getDarkScale, setter=self._ffcWidget.setDarkScale
187
- ),
188
- "axis-angle-x": _getterSetter(
189
- getter=self.rotationAngle._laminoAngle.getAngle,
190
- setter=self.rotationAngle._laminoAngle.setAngle,
191
- ),
192
- "axis-angle-y": _getterSetter(
193
- getter=self.rotationAngle._axisAngleY.getAngle,
194
- setter=self.rotationAngle._axisAngleY.setAngle,
195
- ),
196
- "axis-angle-z": _getterSetter(
197
- getter=self.rotationAngle._axisAngleZ.getAngle,
198
- setter=self.rotationAngle._axisAngleZ.setAngle,
199
- ),
200
- "center-position-x": _getterSetter(
201
- getter=self.centeringWidget.getXCenter,
202
- setter=self.centeringWidget.setXCenter,
203
- ),
204
- "center-position-z": _getterSetter(
205
- getter=self.centeringWidget.getZCenter,
206
- setter=self.centeringWidget.setZCenter,
207
- ),
208
- "overall-angle": _getterSetter(
209
- getter=self.rotationAngle._overallAngle.getAngle,
210
- setter=self.rotationAngle._setOverallAngleI,
211
- ),
212
- "pixel-size": _getterSetter(
213
- getter=self.getPixelSize, setter=self.setPixelSize
214
- ),
215
- "half-acquisition": _getterSetter(
216
- getter=self.isHalfAcquisition, setter=self._halfAcqCB.setChecked
217
- ),
218
- "blend": _getterSetter(getter=self.isBlend, setter=self.setBlend),
219
- "adjust-mean": _getterSetter(
220
- getter=self.isAdjustMean, setter=self.setAdjustMean
221
- ),
222
- }
223
- _TofuOptionLoader.__init__(self, options=options, childs=[self._phaseRetrieval])
224
-
225
- # connect
226
- self._halfAcqCB.toggled.connect(self._updateFFCOptions)
227
-
228
- def _updateFFCOptions(self):
229
- # if we want the half acquisition, for now we force the ffc to be done
230
- # in preprocessing
231
- self._ffcWidget.forcePreprocessing(self._halfAcqCB.isChecked())
232
- self._blendCB.setVisible(self._halfAcqCB.isChecked())
233
- self._adjustMeanCB.setVisible(self._halfAcqCB.isChecked())
234
-
235
- def loadFromScan(self, scanID):
236
- if scanID is None:
237
- return
238
- try:
239
- nFile = getTomo_N(scanID)
240
- self.setNumber(nFile)
241
- except Exception as error:
242
- _logger.error(error)
243
-
244
- self.rotationAngle.loadFromScan(scanID=scanID)
245
- self.centeringWidget.loadFromScan(scanID=scanID)
246
- self._ffcWidget.loadFromScan(scanID=scanID)
247
- self._phaseRetrieval.loadFromScan(scanID=scanID)
248
-
249
- pixelSize = getPixelSize(scanID)
250
- if pixelSize is not None and self.pixelSizeIsLocked() is False:
251
- self.setPixelSize(float(pixelSize))
252
-
253
-
254
- class _FFCConfigWidget(qt.QGroupBox):
255
- """Widget dedicated to the parameters used for the flat field correction"""
256
-
257
- _absortivityActivated = qt.Signal()
258
- """Signal emitted when the absorptivity is activated"""
259
-
260
- def __init__(self, parent):
261
- super(_FFCConfigWidget, self).__init__("flat field correction", parent)
262
- self.setLayout(qt.QGridLayout())
263
-
264
- self._whenGrp = _FFCWhenWidget(parent=self)
265
- self.layout().addWidget(qt.QLabel("when"), 0, 0)
266
- self.layout().addWidget(self._whenGrp, 0, 1)
267
-
268
- self.layout().addWidget(qt.QLabel("method"), 1, 0)
269
- self._method = qt.QComboBox(parent=self)
270
- self._method.addItem("median")
271
- self._method.addItem("Average")
272
- self.layout().addWidget(self._method, 1, 1)
273
-
274
- self.__absortivityLabel = qt.QLabel("absorptivity (*)")
275
- self.__absortivityLabel.setToolTip(
276
- "Activating absortivity will " "deactivate phase retrieval"
277
- )
278
- self.layout().addWidget(self.__absortivityLabel, 2, 0)
279
-
280
- self._absortivity = qt.QCheckBox(parent=self)
281
- self.layout().addWidget(self._absortivity, 2, 1)
282
- self._absortivity.setChecked(True)
283
-
284
- self.layout().addWidget(qt.QLabel("remove Nan and Inf"), 3, 0)
285
- self._removeNanInf = qt.QCheckBox(parent=self)
286
- self.layout().addWidget(self._removeNanInf, 3, 1)
287
- self._removeNanInf.setChecked(True)
288
-
289
- self.layout().addWidget(qt.QLabel("dark scale"), 4, 0)
290
- self._darkScaleSB = qt.QDoubleSpinBox(parent=self)
291
- self._darkScaleSB.setMinimum(0.0)
292
- self._darkScaleSB.setValue(1.0)
293
- self._darkScaleSB.setSingleStep(0.1)
294
- self.layout().addWidget(self._darkScaleSB, 4, 1)
295
-
296
- self.layout().addWidget(qt.QLabel("darks"), 5, 0)
297
- self._darksLE = qt.QLineEdit("", parent=self)
298
- self.layout().addWidget(self._darksLE, 5, 1)
299
- self.layout().addWidget(qt.QLabel("flats"), 6, 0)
300
- self._flatsLE = qt.QLineEdit("", parent=self)
301
- self.layout().addWidget(self._flatsLE, 6, 1)
302
-
303
- self.layout().addWidget(qt.QLabel("second flats"), 7, 0)
304
- self._secondFlatsLE = qt.QLineEdit("", parent=self)
305
- self.layout().addWidget(self._secondFlatsLE, 7, 1)
306
-
307
- self._absortivity.toggled.connect(self._absortivityStatusChanged)
308
-
309
- # expose API
310
- self.getWhenApplyFFC = self._whenGrp.getWhen
311
- self.setWhenApplyFFC = self._whenGrp.setWhen
312
- self.forcePreprocessing = self._whenGrp.forcePreprocessing
313
-
314
- def _absortivityStatusChanged(self, checked):
315
- if checked is True:
316
- self._absortivityActivated.emit()
317
-
318
- def uncheckedAbsorptivity(self):
319
- self._absortivity.setChecked(False)
320
-
321
- def getMethod(self):
322
- return self._method.currentText()
323
-
324
- def setMethod(self, method):
325
- _method = method
326
- if _method.lower == "median":
327
- _method = "median"
328
- if _method.title() == "Average":
329
- _method = "Average"
330
- index = self._method.findText(_method)
331
- if index < 0:
332
- _logger.warning("fail to set method %s, unrecognized method: ", _method)
333
- else:
334
- self._method.setCurrentIndex(index)
335
-
336
- def setAbsortivity(self, value=True):
337
- _value = value
338
- if _value == "":
339
- _value = True
340
- self._absortivity.setChecked(_value)
341
-
342
- def setNanAndInf(self, value=True):
343
- _value = value
344
- if _value == "":
345
- _value = True
346
- self._removeNanInf.setChecked(_value)
347
-
348
- def requireAbsorptivity(self):
349
- return self._absortivity.isChecked()
350
-
351
- def removeNanAndInf(self):
352
- return self._removeNanInf.isChecked()
353
-
354
- def getDarks(self):
355
- if self._darksLE.text() == "":
356
- return None
357
- else:
358
- return self._darksLE.text()
359
-
360
- def setDarks(self, val):
361
- self._darksLE.setText(val)
362
-
363
- def getFlats(self):
364
- if self._flatsLE.text() == "":
365
- return None
366
- else:
367
- return self._flatsLE.text()
368
-
369
- def setFlats(self, val):
370
- self._flatsLE.setText(val)
371
-
372
- def getSecondFlats(self):
373
- if self._secondFlatsLE.text() == "":
374
- return None
375
- else:
376
- return self._secondFlatsLE.text()
377
-
378
- def setSecondFlats(self, val):
379
- self._secondFlatsLE.setText(val)
380
-
381
- def hasDarks(self):
382
- return self._darksLE.text() != ""
383
-
384
- def getDarkScale(self):
385
- if self.hasDarks() is False:
386
- return None
387
- else:
388
- return float(self._darkScaleSB.value())
389
-
390
- def setDarkScale(self, value):
391
- if value is not None:
392
- self._darkScaleSB.setValue(float(value))
393
-
394
- def resetDarkScale(self):
395
- self._darkScaleSB.setValue(1.0)
396
-
397
- def loadFromScan(self, scanID):
398
- try:
399
- flats, secondFlat = getFlats(scan=scanID)
400
- self.setFlats(flats or "")
401
- self.setSecondFlats(secondFlat or "")
402
- darkN = getDARK_N(scanID)
403
- if darkN is not None:
404
- self._darkScaleSB.setValue(1.0 / int(darkN))
405
- darkFile = getDark(scan=scanID)
406
- if darkFile is not None:
407
- self.setDarks(darkFile)
408
- # in this case dark is already normalized, set dark scale to 1.0
409
- if os.path.basename(darkFile) in ("dark.edf", "darkHST.edf"):
410
- self.resetDarkScale()
411
- except Exception as error:
412
- _logger.error(error)
413
-
414
-
415
- class _FFCWhenWidget(qt.QWidget):
416
- def __init__(self, parent):
417
- qt.QWidget.__init__(self, parent)
418
- self.setLayout(qt.QHBoxLayout())
419
- self.layout().setContentsMargins(0, 0, 0, 0)
420
- self._group = qt.QButtonGroup(parent=self)
421
-
422
- name = FFCWhen.on_the_fly.name.replace("_", " ")
423
- self._onTheFlyQRB = qt.QRadioButton(name, self)
424
- self._onTheFlyQRB.setToolTip(
425
- "process flat field correction during "
426
- "reconstruction. Avoid multiple io read."
427
- )
428
- self.layout().addWidget(self._onTheFlyQRB)
429
- self._group.addButton(self._onTheFlyQRB)
430
-
431
- name = FFCWhen.preprocessing.name.replace("_", " ")
432
- self._preProcQRB = qt.QRadioButton(name, self)
433
- self._preProcQRB.setToolTip(
434
- "make flat field on a preprocessing step. "
435
- "Can be interesting if you intend to test "
436
- "several reconstruction parameters"
437
- )
438
- self.layout().addWidget(self._preProcQRB)
439
- self._group.addButton(self._preProcQRB)
440
-
441
- # setting: default on the fly
442
- self._onTheFlyQRB.setChecked(True)
443
-
444
- def getWhen(self):
445
- if self._onTheFlyQRB.isChecked():
446
- return FFCWhen.on_the_fly
447
- elif self._preProcQRB.isChecked():
448
- return FFCWhen.preprocessing
449
- else:
450
- raise ValueError('No "when" defined')
451
-
452
- def setWhen(self, name):
453
- if isinstance(name, FFCWhen):
454
- if name is FFCWhen.on_the_fly:
455
- self._onTheFlyQRB.setChecked(True)
456
- elif name is FFCWhen.preprocessing:
457
- self._preProcQRB.setChecked(True)
458
- else:
459
- raise ValueError("FFCWhen type is not managed")
460
- elif type(name) is str:
461
- try:
462
- _name = name.split(".")[-1]
463
- # name.split('.')[-1] because name can be given as FFCWhen.on_the_fly...
464
- _when_instance = getattr(FFCWhen, _name.lower().replace(" ", "_"))
465
- except Exception:
466
- _logger.error(f"fail to determine 'FFCWhen' value from {name}")
467
- else:
468
- self.setWhen(_when_instance)
469
- else:
470
- raise ValueError("name should be a str or a FFCWhen")
471
-
472
- def forcePreprocessing(self, force_):
473
- old = self.blockSignals(True)
474
- if force_:
475
- self._preProcQRB.setChecked(True)
476
- self.setEnabled(not force_)
477
- self.blockSignals(old)
478
-
479
-
480
- class CenteringTofuGroupBox(qt.QGroupBox):
481
- """
482
- Widget used to display centering information
483
- """
484
-
485
- def __init__(self, parent):
486
- qt.QGroupBox.__init__(self, "centering", parent)
487
- self.setLayout(qt.QGridLayout())
488
- self.layout().addWidget(qt.QLabel("x center", parent=self), 0, 0)
489
- self._xCenterLE = qt.QLineEdit("0", parent=self)
490
- validator = qt.QDoubleValidator(parent=self)
491
- self._xCenterLE.setValidator(validator)
492
- self.layout().addWidget(self._xCenterLE, 0, 1)
493
-
494
- self.layout().addWidget(qt.QLabel("y center", parent=self), 1, 0)
495
- self._yCenterLE = qt.QLineEdit("0", parent=self)
496
- self._yCenterLE.setValidator(validator)
497
- self.layout().addWidget(self._yCenterLE, 1, 1)
498
-
499
- self._lockButton = PadlockButton(parent=self)
500
- self._lockButton.setSizePolicy(
501
- qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding
502
- )
503
- self.layout().addWidget(self._lockButton, 0, 2, 2, 2)
504
-
505
- # expose API
506
- self.isLocked = self._lockButton.isLocked
507
-
508
- def getXCenter(self):
509
- return float(self._xCenterLE.text())
510
-
511
- def setXCenter(self, value):
512
- self._xCenterLE.setText(str(value))
513
-
514
- def getZCenter(self):
515
- return float(self._yCenterLE.text())
516
-
517
- def setZCenter(self, value):
518
- self._yCenterLE.setText(str(value))
519
-
520
- def loadFromScan(self, scanID):
521
- if self.isLocked() is False:
522
- # can be set from Dim 1 and Dim 2
523
- # question: here to avoid interpolation we simply make an integer
524
- # division which give an integer
525
- dim1, dim2 = getDim1Dim2(scanID)
526
- for dim, lineEdit in zip((dim1, dim2), (self._xCenterLE, self._yCenterLE)):
527
- if dim is not None:
528
- lineEdit.setText(str(int(dim / 2)))
529
-
530
- # try to set x center from the .par file
531
- try:
532
- parFile = os.path.join(scanID, os.path.basename(scanID) + ".par")
533
- if os.path.exists(parFile) is True:
534
- params = getParametersFromParOrInfo(parFile)
535
- rot_axis_pos = None
536
- for k in ("ROTATION_AXIS_POS", "ROTATION_AXIS_POSITION"):
537
- if k.lower() in params:
538
- rot_axis_pos = params[k.lower()]
539
-
540
- if rot_axis_pos is not None:
541
- self._xCenterLE.setText(str(rot_axis_pos))
542
- except Exception as error:
543
- _logger.error(error)
544
-
545
-
546
- class NbFilesWidget(qt.QWidget):
547
- """
548
- Widget to display the number of file (projection) to be send to tofu
549
- """
550
-
551
- def __init__(self, parent=None):
552
- qt.QWidget.__init__(self, parent=parent)
553
- self.setLayout(qt.QGridLayout())
554
- self.layout().addWidget(qt.QLabel("number of files", parent=self), 0, 0)
555
- self._nFileLE = qt.QLineEdit("0", parent=self)
556
- validator = qt.QIntValidator()
557
- validator.setBottom(0)
558
- self._nFileLE.setValidator(validator)
559
- self.layout().addWidget(self._nFileLE, 0, 1)
560
-
561
- def setNumberOfFiles(self, n):
562
- self._nFileLE.setText(str(n))
563
-
564
- def getNumberOfFiles(self):
565
- if self._nFileLE.text().isdigit():
566
- return int(self._nFileLE.text())
567
- else:
568
- return 0
569
-
570
-
571
- class AngleIllustrations(qt.QWidget):
572
- def __init__(self, parent):
573
- qt.QWidget.__init__(self, parent)
574
- self.setLayout(qt.QVBoxLayout())
575
- self.setContentsMargins(0, 0, 0, 0)
576
- self._infoLabel = qt.QLabel(parent=self)
577
- icon = icons.getQIcon("information")
578
- self._infoLabel.setPixmap(icon.pixmap(qt.QSize(32, 32)))
579
- self.layout().addWidget(self._infoLabel)
580
-
581
- self.illustrationCB = qt.QComboBox(parent=self)
582
- self.illustrationCB.addItem("lamino angle")
583
- self.illustrationCB.addItem(PSI_CHAR + " angle")
584
- self.layout().addWidget(self.illustrationCB)
585
-
586
- self._illustrations = qt.QWidget(parent=self)
587
- self._illustrations.setLayout(qt.QHBoxLayout())
588
- self.layout().addWidget(self._illustrations)
589
- self._laminoAngleIllustration = _IllustrationWidget(
590
- parent=self, img="lamino_angle"
591
- )
592
- self._psiAngleIllustration = _IllustrationWidget(parent=self, img="psi_angle")
593
- self._illustrations.setMinimumSize(qt.QSize(200, 200))
594
- self._illustrations.setSizePolicy(
595
- qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding
596
- )
597
-
598
- self._illustrations.setContentsMargins(0, 0, 0, 0)
599
- self._illustrations.layout().setSpacing(0)
600
- self._illustrations.layout().addWidget(self._laminoAngleIllustration)
601
- self._illustrations.layout().addWidget(self._psiAngleIllustration)
602
- self.layout().addWidget(self._illustrations)
603
- self.setActiveIllustration("lamino angle")
604
- self.illustrationCB.currentIndexChanged[str].connect(self.setActiveIllustration)
605
-
606
- def setActiveIllustration(self, name):
607
- assert name in ("lamino angle", PSI_CHAR + " angle", THETA_CHAR + " angle")
608
- if name == THETA_CHAR + " angle":
609
- _logger.info("No illustration of the delta angle for the moment")
610
- return
611
- self.blockSignals(True)
612
- index = self.illustrationCB.findText(name)
613
- assert index >= 0
614
- self.illustrationCB.setCurrentIndex(index)
615
-
616
- self._laminoAngleIllustration.setVisible(name == "lamino angle")
617
- self._psiAngleIllustration.setVisible(name == PSI_CHAR + " angle")
618
-
619
- self.blockSignals(False)
620
-
621
-
622
- class RotationAngleGroupBox(qt.QGroupBox):
623
- def __init__(self, parent):
624
- qt.QGroupBox.__init__(self, "angles", parent)
625
- self.setLayout(qt.QHBoxLayout())
626
-
627
- self.layout().setContentsMargins(0, 0, 0, 0)
628
- self.layout().setSpacing(0)
629
-
630
- self._angles = qt.QWidget(parent=self)
631
- self._angles.setLayout(qt.QVBoxLayout())
632
- self._angles.setContentsMargins(0, 0, 0, 0)
633
- self.layout().addWidget(self._angles)
634
-
635
- self._laminoAngle = _AngleWidget(
636
- parent=self._angles,
637
- name="rotation axis tilt",
638
- defaultVal=90,
639
- lockable=True,
640
- information=self._showLaminoAngleInfo,
641
- )
642
- self._angles.layout().addWidget(self._laminoAngle)
643
- self._axisAngleY = _AngleWidget(
644
- parent=self._angles,
645
- name=(PSI_CHAR + " angle"),
646
- lockable=True,
647
- information=self._showPsiAngleInfo,
648
- )
649
- self._angles.layout().addWidget(self._axisAngleY)
650
-
651
- self._axisAngleZ = _AngleWidget(
652
- parent=self._angles, name=(THETA_CHAR + " angle"), lockable=True
653
- )
654
- self._angles.layout().addWidget(self._axisAngleZ)
655
- self._axisAngleZ.setVisible(False)
656
-
657
- self._overallAngle = _AngleWidget(
658
- parent=self, name="overall angle", defaultVal=360, lockable=True
659
- )
660
- self._angles.layout().addWidget(self._overallAngle)
661
-
662
- self._spacer = qt.QWidget(parent=self._angles)
663
- self._spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
664
- self._angles.layout().addWidget(self._spacer)
665
-
666
- self._infoLamino = None
667
- self._infoPsi = None
668
-
669
- # expose some API
670
- self.getLaminoAngle = self._laminoAngle.getAngle
671
- self.getPsiAngle = self._axisAngleY.getAngle
672
-
673
- def _showLaminoAngleInfo(self):
674
- self.getInfoLaminoDialog().show()
675
- self.getInfoLaminoDialog().raise_()
676
- self.getInfoLaminoDialog().activateWindow()
677
-
678
- def _showPsiAngleInfo(self):
679
- self.getPsiLaminoDialog().show()
680
- self.getPsiLaminoDialog().raise_()
681
- self.getPsiLaminoDialog().activateWindow()
682
-
683
- def getInfoLaminoDialog(self):
684
- if self._infoLamino is None:
685
- self._infoLamino = _IllustrationDialog(
686
- parent=self, img="lamino_angle", title="information about lamino angle"
687
- )
688
- return self._infoLamino
689
-
690
- def getPsiLaminoDialog(self):
691
- if self._infoPsi is None:
692
- self._infoPsi = _IllustrationDialog(
693
- parent=self,
694
- img="psi_angle",
695
- title=" ".join(("information about", PSI_CHAR, "angle")),
696
- )
697
- return self._infoPsi
698
-
699
- def loadFromScan(self, scanID):
700
- assert type(scanID) is str
701
- _info_file = os.path.join(scanID, os.path.basename(scanID) + ".info")
702
- if os.path.isfile(_info_file) is True:
703
- info = getParametersFromParOrInfo(_info_file)
704
- if self._laminoAngle.isLocked() is False and "ctangle" in info:
705
- self._laminoAngle.setAngle(90.0 - float(info["ctangle"]))
706
- if self._overallAngle.isLocked() is False and "scanrange" in info:
707
- self._overallAngle.setAngle(float(info["scanrange"]))
708
-
709
- def _setOverallAngleI(self, val):
710
- """
711
- Set the inverse value to the lamino angle
712
-
713
- :param val:
714
- :return:
715
- """
716
- _val = float(val) * -1.0
717
- self._overallAngle.setAngle(_val)
718
-
719
-
720
- class PhaseRetrievalWidget(_TofuOptionLoader, qt.QGroupBox):
721
- """
722
- Widget sued to defined the phase retrieval
723
- """
724
-
725
- activated = qt.Signal()
726
- """Emitted when the phase retrieval is activated"""
727
-
728
- METHODS = "tie", "ctf", "ctfhalfsin", "qp", "qphalfsine", "qp2"
729
- DEFAULT_METHOD = "tie"
730
-
731
- def __init__(self, parent):
732
- qt.QGroupBox.__init__(self, "phase retrieval (*)", parent)
733
- self.setToolTip("Activating phase retrieval will deactivate " "absorptivity")
734
- self.setLayout(qt.QGridLayout())
735
- # retrieval method
736
- self._retrievalMethodCB = qt.QComboBox(parent=self)
737
- for _method in self.METHODS:
738
- self._retrievalMethodCB.addItem(_method)
739
- assert self.DEFAULT_METHOD in self.METHODS
740
- self._retrievalMethodCB.setCurrentIndex(
741
- self._retrievalMethodCB.findText(self.DEFAULT_METHOD)
742
- )
743
- self.layout().addWidget(qt.QLabel("retrieval method:", self), 0, 0)
744
- self.layout().addWidget(self._retrievalMethodCB, 0, 1)
745
-
746
- # energy
747
- self.layout().addWidget(qt.QLabel("energy:", self), 1, 0)
748
- self._energy = qt.QLineEdit("65.0", parent=self)
749
- validator = qt.QDoubleValidator(parent=self._energy)
750
- self._energy.setValidator(validator)
751
- self.layout().addWidget(self._energy, 1, 1)
752
- self._energyLockButton = PadlockButton(parent=self)
753
- self.layout().addWidget(self._energyLockButton, 1, 2)
754
-
755
- # regularization rate
756
- self.layout().addWidget(qt.QLabel("regularization rate:", self), 3, 0)
757
- self._regularizationRate = qt.QLineEdit("1.5", parent=self)
758
- validator = qt.QDoubleValidator(parent=self._regularizationRate)
759
- self._regularizationRate.setValidator(validator)
760
- self.layout().addWidget(self._regularizationRate, 3, 1)
761
- self._regRateLockButton = PadlockButton(parent=self)
762
- self.layout().addWidget(self._regRateLockButton, 3, 2)
763
-
764
- # thresholding rate
765
- self.layout().addWidget(qt.QLabel("thresholding rate:", self), 4, 0)
766
- self._thresholdingRate = qt.QLineEdit("0.4", parent=self)
767
- validator = qt.QDoubleValidator(parent=self._thresholdingRate)
768
- self._thresholdingRate.setValidator(validator)
769
- self.layout().addWidget(self._thresholdingRate, 4, 1)
770
-
771
- # propagation distance
772
- self.layout().addWidget(qt.QLabel("propagation distance (m):", self), 5, 0)
773
- self._propagationDistance = qt.QLineEdit("0.08", parent=self)
774
- validator = qt.QDoubleValidator(parent=self._propagationDistance)
775
- self._propagationDistance.setValidator(validator)
776
- self.layout().addWidget(self._propagationDistance, 5, 1)
777
- self._propaDistLockButton = PadlockButton(parent=self)
778
- self.layout().addWidget(self._propaDistLockButton, 5, 2)
779
-
780
- # create some more speaking API
781
- self.energyIsLocked = self._energyLockButton.isLocked
782
- self.getRetrievalMethod = self._retrievalMethodCB.currentText
783
- self.propaDistIsLocked = self._propaDistLockButton.isLocked
784
-
785
- # signal/slot connection
786
- self.toggled.connect(self.__toggleCallback)
787
-
788
- options = {
789
- "retrieval-method": _getterSetter(
790
- getter=self._getRetrievalMethod, setter=self.setRetrievalMethod
791
- ),
792
- "energy": _getterSetter(getter=self._getEnergy, setter=self.setEnergy),
793
- "propagation-distance": _getterSetter(
794
- getter=self._getPropagationDistance, setter=self.setPropagationDistance
795
- ),
796
- "regularization-rate": _getterSetter(
797
- getter=self._getRegularizationRate, setter=self.setRegularizationRate
798
- ),
799
- "thresholding-rate": _getterSetter(
800
- getter=self._getThresholdingRate, setter=self.setThresholdingRate
801
- ),
802
- }
803
- _TofuOptionLoader.__init__(self, options=options)
804
-
805
- def loadFromScan(self, scanID):
806
- _info_file = os.path.join(scanID, os.path.basename(scanID) + ".info")
807
- if os.path.isfile(_info_file) is True:
808
- energy = getClosestEnergy(scanID)
809
- if energy is not None and self.energyIsLocked() is False:
810
- self.setEnergy(energy)
811
- info = getParametersFromParOrInfo(_info_file)
812
- if "distance" in info and self.propaDistIsLocked() is False:
813
- try:
814
- dst = float(info["distance"])
815
- # convert to meter
816
- dst = dst / 1000.0
817
- self.setPropagationDistance(dst)
818
- except Exception:
819
- pass
820
-
821
- def setUnchecked(self):
822
- self.setChecked(False)
823
-
824
- def __toggleCallback(self, checked):
825
- if checked is True:
826
- self.activated.emit()
827
-
828
- # retrieval method
829
- def _getRetrievalMethod(self):
830
- if self.isChecked() is True:
831
- return self.getRetrievalMethod()
832
- else:
833
- return None
834
-
835
- def setRetrievalMethod(self, method):
836
- if method is not None:
837
- if method not in self.METHODS:
838
- _logger.error("method %s is not recognized as a retrieval " "method")
839
- else:
840
- index = self._retrievalMethodCB.find(method)
841
- self._retrievalMethodCB.setCurrentIndex(index)
842
-
843
- # energy
844
- def getEnergy(self):
845
- return float(self._energy.text())
846
-
847
- def _getEnergy(self):
848
- "Return None if not activated, otherwise the value"
849
- if self.isChecked() is True:
850
- return self.getEnergy()
851
-
852
- def setEnergy(self, energy):
853
- if energy is not None:
854
- self._energy.setText(str(energy))
855
-
856
- # propagation distance
857
- def getPropagationDistance(self):
858
- return float(self._propagationDistance.text())
859
-
860
- def _getPropagationDistance(self):
861
- if self.isChecked() is True:
862
- return self.getPropagationDistance()
863
- else:
864
- return None
865
-
866
- def setPropagationDistance(self, distance):
867
- if distance is not None:
868
- self._propagationDistance.setText(str(distance))
869
-
870
- # regularization rate
871
- def getRegularizationRate(self):
872
- return float(self._regularizationRate.text())
873
-
874
- def _getRegularizationRate(self):
875
- if self.isChecked() is True:
876
- return self.getRegularizationRate()
877
- else:
878
- return None
879
-
880
- def setRegularizationRate(self, rate):
881
- if rate is not None:
882
- self._regularizationRate.setText(str(rate))
883
-
884
- # thresholding rate
885
- def getThresholdingRate(self):
886
- return float(self._thresholdingRate.text())
887
-
888
- def _getThresholdingRate(self):
889
- if self.isChecked() is True:
890
- return self.getThresholdingRate()
891
- else:
892
- return None
893
-
894
- def setThresholdingRate(self, rate):
895
- if rate is not None:
896
- self._thresholdingRate.setText(str(rate))