tomwer 1.2.8__py3-none-any.whl → 1.3.0a0__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 (253) hide show
  1. orangecontrib/tomwer/tutorials/icat_publication.ows +58 -0
  2. orangecontrib/tomwer/widgets/__init__.py +1 -0
  3. orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +2 -2
  4. orangecontrib/tomwer/widgets/control/DataListOW.py +9 -7
  5. orangecontrib/tomwer/widgets/control/DataSelectorOW.py +21 -10
  6. orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +11 -5
  7. orangecontrib/tomwer/widgets/control/EmailOW.py +4 -4
  8. orangecontrib/tomwer/widgets/control/NXTomomillOW.py +31 -18
  9. orangecontrib/tomwer/widgets/control/NXtomoConcatenate.py +14 -7
  10. orangecontrib/tomwer/widgets/control/NotifierOW.py +1 -0
  11. orangecontrib/tomwer/widgets/control/VolumeSelector.py +7 -4
  12. orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +182 -182
  13. orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +4 -4
  14. orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +4 -4
  15. orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +3 -3
  16. orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +2 -0
  17. orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +3 -3
  18. orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +3 -3
  19. orangecontrib/tomwer/widgets/icat/PublishProcessedDataOW.py +115 -0
  20. orangecontrib/tomwer/widgets/icat/RawDataScreenshotCreatorOW.py +98 -0
  21. orangecontrib/tomwer/widgets/icat/SaveToGalleryAndPublishOW.py +129 -0
  22. orangecontrib/tomwer/widgets/icat/__init__.py +13 -0
  23. orangecontrib/tomwer/widgets/icat/icons/add_gallery.png +0 -0
  24. orangecontrib/tomwer/widgets/icat/icons/add_gallery.svg +82 -0
  25. orangecontrib/tomwer/widgets/icat/icons/publish_processed_data.png +0 -0
  26. orangecontrib/tomwer/widgets/icat/icons/publish_processed_data.svg +95 -0
  27. orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.png +0 -0
  28. orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.svg +143 -0
  29. orangecontrib/tomwer/widgets/icons/tomwer_data_portal.png +0 -0
  30. orangecontrib/tomwer/widgets/icons/tomwer_data_portal.svg +76 -0
  31. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +9 -8
  32. orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +3 -3
  33. orangecontrib/tomwer/widgets/reconstruction/NabuHelicalPrepareWeightsDoubleOW.py +179 -169
  34. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +23 -0
  35. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +39 -5
  36. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +7 -13
  37. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +7 -17
  38. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +3 -4
  39. orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +1 -1
  40. orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +3 -3
  41. orangecontrib/tomwer/widgets/visualization/VolumeViewerOW.py +3 -29
  42. tomwer/__main__.py +11 -58
  43. tomwer/app/canvas.py +8 -0
  44. tomwer/app/canvas_launcher/config.py +13 -11
  45. tomwer/app/darkref.py +1 -1
  46. tomwer/app/darkrefpatch.py +1 -1
  47. tomwer/app/imagekeyeditor.py +5 -5
  48. tomwer/app/imagekeyupgrader.py +5 -5
  49. tomwer/app/intensitynormalization.py +2 -2
  50. tomwer/app/radiostack.py +2 -2
  51. tomwer/app/zstitching.py +74 -3
  52. tomwer/core/cluster/cluster.py +26 -0
  53. tomwer/core/log/logger.py +7 -5
  54. tomwer/core/process/conditions/filters.py +1 -1
  55. tomwer/core/process/control/datalistener/datalistener.py +3 -3
  56. tomwer/core/process/control/nxtomoconcatenate.py +13 -13
  57. tomwer/core/process/control/nxtomomill.py +83 -25
  58. tomwer/core/process/control/scantransfer.py +11 -10
  59. tomwer/core/process/control/scanvalidator.py +3 -2
  60. tomwer/core/process/control/test/test_concatenate_nxtomos.py +9 -9
  61. tomwer/core/process/control/test/test_email.py +4 -4
  62. tomwer/core/process/control/test/test_h52nx_process.py +59 -7
  63. tomwer/core/process/control/test/test_volume_link.py +64 -64
  64. tomwer/core/process/control/timer.py +1 -1
  65. tomwer/core/process/control/volumesymlink.py +200 -200
  66. tomwer/core/process/edit/darkflatpatch.py +6 -6
  67. tomwer/core/process/edit/imagekeyeditor.py +17 -18
  68. tomwer/core/process/icat/__init__.py +0 -0
  69. tomwer/core/process/icat/createscreenshots.py +100 -0
  70. tomwer/core/process/icat/gallery.py +377 -0
  71. tomwer/core/process/icat/icatbase.py +36 -0
  72. tomwer/core/process/icat/publish.py +228 -0
  73. tomwer/core/process/icat/screenshots.py +26 -0
  74. tomwer/core/process/output.py +52 -0
  75. tomwer/core/process/reconstruction/axis/axis.py +17 -10
  76. tomwer/core/process/reconstruction/axis/mode.py +4 -0
  77. tomwer/core/process/reconstruction/axis/params.py +9 -4
  78. tomwer/core/process/reconstruction/darkref/darkrefs.py +8 -6
  79. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +1 -1
  80. tomwer/core/process/reconstruction/darkref/params.py +1 -1
  81. tomwer/core/process/reconstruction/lamino/tofu.py +4 -4
  82. tomwer/core/process/reconstruction/nabu/castvolume.py +1 -1
  83. tomwer/core/process/reconstruction/nabu/helical.py +9 -5
  84. tomwer/core/process/reconstruction/nabu/nabucommon.py +32 -62
  85. tomwer/core/process/reconstruction/nabu/nabuscores.py +387 -61
  86. tomwer/core/process/reconstruction/nabu/nabuslices.py +33 -21
  87. tomwer/core/process/reconstruction/nabu/nabuvolume.py +37 -14
  88. tomwer/core/process/reconstruction/nabu/settings.py +2 -2
  89. tomwer/core/process/reconstruction/nabu/utils.py +129 -24
  90. tomwer/core/process/reconstruction/output.py +108 -0
  91. tomwer/core/process/reconstruction/saaxis/saaxis.py +233 -263
  92. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +140 -86
  93. tomwer/core/process/reconstruction/scores/params.py +4 -1
  94. tomwer/core/process/reconstruction/scores/scores.py +13 -0
  95. tomwer/core/process/reconstruction/test/test_axis_params.py +2 -2
  96. tomwer/core/process/reconstruction/test/test_darkref.py +3 -3
  97. tomwer/core/process/reconstruction/test/test_darkref_copy.py +3 -3
  98. tomwer/core/process/reconstruction/test/test_saaxis.py +3 -4
  99. tomwer/core/process/reconstruction/test/test_sadeltabeta.py +2 -2
  100. tomwer/core/process/stitching/nabustitcher.py +2 -2
  101. tomwer/core/process/test/test_axis.py +6 -6
  102. tomwer/core/process/test/test_dark_and_flat.py +10 -7
  103. tomwer/core/process/test/test_data_transfer.py +7 -6
  104. tomwer/core/process/test/test_nabu.py +4 -4
  105. tomwer/core/process/test/test_normalization.py +2 -2
  106. tomwer/core/scan/edfscan.py +4 -1
  107. tomwer/core/scan/hdf5scan.py +19 -500
  108. tomwer/core/scan/nxtomoscan.py +532 -0
  109. tomwer/core/scan/scanbase.py +42 -20
  110. tomwer/core/scan/scanfactory.py +13 -13
  111. tomwer/core/scan/test/test_future_scan.py +2 -2
  112. tomwer/core/scan/test/test_h5.py +12 -10
  113. tomwer/core/scan/test/test_process_registration.py +2 -2
  114. tomwer/core/scan/test/test_scan.py +4 -3
  115. tomwer/core/settings.py +20 -0
  116. tomwer/core/test/test_scanutils.py +8 -7
  117. tomwer/core/test/test_utils.py +33 -26
  118. tomwer/core/utils/__init__.py +0 -466
  119. tomwer/core/utils/deprecation.py +1 -1
  120. tomwer/core/utils/dictutils.py +14 -0
  121. tomwer/core/utils/lbsram.py +35 -0
  122. tomwer/core/utils/nxtomoutils.py +1 -1
  123. tomwer/core/utils/scanutils.py +6 -6
  124. tomwer/core/utils/spec.py +263 -0
  125. tomwer/core/volume/volumefactory.py +2 -2
  126. tomwer/gui/cluster/slurm.py +260 -60
  127. tomwer/gui/cluster/test/test_cluster.py +13 -0
  128. tomwer/gui/cluster/test/test_supervisor.py +2 -2
  129. tomwer/gui/configuration/__init__.py +0 -0
  130. tomwer/gui/{reconstruction/nabu → configuration}/action.py +1 -32
  131. tomwer/gui/configuration/level.py +22 -0
  132. tomwer/gui/control/actions.py +54 -0
  133. tomwer/gui/control/datalist.py +78 -16
  134. tomwer/gui/control/datalistener.py +4 -16
  135. tomwer/gui/control/{email.py → emailnotifier.py} +9 -18
  136. tomwer/gui/control/history.py +2 -2
  137. tomwer/gui/control/observations.py +2 -2
  138. tomwer/gui/control/reducedarkflatselector.py +1 -1
  139. tomwer/gui/control/selectorwidgetbase.py +36 -9
  140. tomwer/gui/control/serie/seriecreator.py +5 -22
  141. tomwer/gui/control/test/test_email.py +1 -1
  142. tomwer/gui/control/test/test_scanvalidator.py +6 -5
  143. tomwer/gui/control/test/test_single_tomo_obj.py +2 -2
  144. tomwer/gui/control/tomoobjdisplaymode.py +8 -0
  145. tomwer/gui/debugtools/datasetgenerator.py +3 -3
  146. tomwer/gui/edit/dkrfpatch.py +16 -22
  147. tomwer/gui/edit/imagekeyeditor.py +8 -11
  148. tomwer/gui/edit/nxtomoeditor.py +111 -44
  149. tomwer/gui/edit/nxtomowarmer.py +4 -4
  150. tomwer/gui/edit/test/test_dkrf_patch.py +7 -7
  151. tomwer/gui/edit/test/test_image_key_editor.py +3 -3
  152. tomwer/gui/edit/test/test_nx_editor.py +40 -16
  153. tomwer/gui/icat/__init__.py +0 -0
  154. tomwer/gui/icat/createscreenshots.py +80 -0
  155. tomwer/gui/icat/gallery.py +214 -0
  156. tomwer/gui/icat/publish.py +187 -0
  157. tomwer/gui/reconstruction/axis/axis.py +171 -57
  158. tomwer/gui/reconstruction/axis/radioaxis.py +80 -95
  159. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +3 -2
  160. tomwer/gui/reconstruction/lamino/tofu/projections.py +1 -1
  161. tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +3 -6
  162. tomwer/gui/reconstruction/nabu/castvolume.py +1 -1
  163. tomwer/gui/reconstruction/nabu/check.py +9 -9
  164. tomwer/gui/reconstruction/nabu/helical.py +29 -12
  165. tomwer/gui/reconstruction/nabu/nabuconfig/base.py +2 -4
  166. tomwer/gui/reconstruction/nabu/nabuconfig/output.py +110 -33
  167. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +9 -12
  168. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +219 -29
  169. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +3 -6
  170. tomwer/gui/reconstruction/nabu/nabuflow.py +12 -20
  171. tomwer/gui/reconstruction/nabu/slices.py +6 -7
  172. tomwer/gui/reconstruction/nabu/volume.py +22 -10
  173. tomwer/gui/reconstruction/normalization/intensity.py +15 -23
  174. tomwer/gui/reconstruction/saaxis/corrangeselector.py +7 -23
  175. tomwer/gui/reconstruction/saaxis/dimensionwidget.py +1 -1
  176. tomwer/gui/reconstruction/saaxis/saaxis.py +7 -9
  177. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +2 -1
  178. tomwer/gui/reconstruction/scores/control.py +2 -9
  179. tomwer/gui/reconstruction/scores/scoreplot.py +11 -5
  180. tomwer/gui/reconstruction/test/test_axis.py +23 -12
  181. tomwer/gui/reconstruction/test/test_lamino.py +8 -3
  182. tomwer/gui/reconstruction/test/test_nabu.py +28 -9
  183. tomwer/gui/reconstruction/test/test_saaxis.py +3 -3
  184. tomwer/gui/reconstruction/test/test_sadeltabeta.py +2 -2
  185. tomwer/gui/settings.py +5 -28
  186. tomwer/gui/stackplot.py +2 -5
  187. tomwer/gui/stitching/action.py +49 -0
  188. tomwer/gui/stitching/config/axisparams.py +7 -24
  189. tomwer/gui/stitching/config/output.py +10 -8
  190. tomwer/gui/stitching/config/positionoveraxis.py +22 -23
  191. tomwer/gui/stitching/normalization.py +117 -0
  192. tomwer/gui/stitching/stitchandbackground.py +4 -6
  193. tomwer/gui/stitching/stitching.py +265 -43
  194. tomwer/gui/stitching/stitching_preview.py +62 -5
  195. tomwer/gui/stitching/stitching_raw.py +2 -5
  196. tomwer/gui/stitching/z_stitching/fineestimation.py +0 -60
  197. tomwer/gui/utils/buttons.py +112 -29
  198. tomwer/gui/utils/inputwidget.py +33 -25
  199. tomwer/gui/utils/scandescription.py +4 -0
  200. tomwer/gui/utils/step.py +144 -0
  201. tomwer/gui/utils/unitsystem.py +2 -5
  202. tomwer/gui/utils/vignettes.py +176 -15
  203. tomwer/gui/visualization/dataviewer.py +1 -18
  204. tomwer/gui/visualization/diffviewer/diffviewer.py +7 -16
  205. tomwer/gui/visualization/diffviewer/shiftwidget.py +2 -5
  206. tomwer/gui/visualization/scanoverview.py +1 -1
  207. tomwer/gui/visualization/sinogramviewer.py +1 -10
  208. tomwer/gui/visualization/test/test_diffviewer.py +3 -3
  209. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +4 -4
  210. tomwer/gui/visualization/test/test_sinogramviewer.py +2 -2
  211. tomwer/gui/visualization/test/test_stacks.py +3 -3
  212. tomwer/gui/visualization/test/test_volumeviewer.py +2 -2
  213. tomwer/io/utils/raw_and_processed_data.py +84 -0
  214. tomwer/io/utils/tomoobj.py +4 -6
  215. tomwer/resources/gui/icons/ruler.png +0 -0
  216. tomwer/resources/gui/icons/ruler.svg +273 -0
  217. tomwer/resources/gui/icons/short_description.png +0 -0
  218. tomwer/resources/gui/icons/short_description.svg +58 -0
  219. tomwer/resources/gui/icons/url.png +0 -0
  220. tomwer/resources/gui/icons/url.svg +58 -0
  221. tomwer/synctools/stacks/edit/darkflatpatch.py +2 -2
  222. tomwer/synctools/stacks/edit/imagekeyeditor.py +2 -2
  223. tomwer/synctools/stacks/reconstruction/axis.py +4 -4
  224. tomwer/synctools/stacks/reconstruction/castvolume.py +2 -2
  225. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +4 -10
  226. tomwer/synctools/stacks/reconstruction/nabu.py +2 -2
  227. tomwer/synctools/stacks/reconstruction/normalization.py +2 -2
  228. tomwer/synctools/stacks/reconstruction/saaxis.py +2 -2
  229. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +2 -2
  230. tomwer/synctools/test/test_darkRefs.py +7 -58
  231. tomwer/synctools/test/test_foldertransfer.py +6 -6
  232. tomwer/synctools/utils/scanstages.py +6 -6
  233. tomwer/tests/conftest.py +34 -0
  234. tomwer/tests/datasets.py +13 -0
  235. tomwer/tests/test_scripts.py +92 -39
  236. tomwer/tests/utils.py +5 -0
  237. tomwer/version.py +3 -3
  238. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/METADATA +39 -44
  239. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/RECORD +248 -209
  240. tomwer/resources/gui/icons/esrf_1.svg +0 -307
  241. tomwer/resources/gui/icons/triangle.svg +0 -80
  242. tomwer/synctools/test/test_scanstages.py +0 -162
  243. tomwer/tests/utils/__init__.py +0 -247
  244. tomwer/tests/utils/utilstest.py +0 -220
  245. /tomwer/app/{saaxis.py → multicor.py} +0 -0
  246. /tomwer/app/{sadeltabeta.py → multipag.py} +0 -0
  247. /tomwer/core/process/control/{email.py → emailnotifier.py} +0 -0
  248. /tomwer-1.2.8-py3.11-nspkg.pth → /tomwer-1.3.0a0-py3.11-nspkg.pth +0 -0
  249. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/LICENSE +0 -0
  250. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/WHEEL +0 -0
  251. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/entry_points.txt +0 -0
  252. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/namespace_packages.txt +0 -0
  253. {tomwer-1.2.8.dist-info → tomwer-1.3.0a0.dist-info}/top_level.txt +0 -0
@@ -56,6 +56,8 @@ from tomwer.core.scan.scanfactory import ScanFactory
56
56
  from tomwer.core.utils import image
57
57
  from tomwer.gui.utils.buttons import PadlockButton
58
58
  from tomwer.gui.utils.qt_utils import block_signals
59
+ from tomwer.gui.settings import EDITING_BACKGROUND_COLOR
60
+ from tomwer.gui.utils.step import StepSizeSelectorWidget
59
61
  from tomwer.synctools.axis import QAxisRP
60
62
 
61
63
  from .CompareImages import CompareImages
@@ -671,12 +673,12 @@ class _AxisManual(qt.QWidget):
671
673
  self._manualSelectionWidget.sigResetZoomRequested.connect(
672
674
  self._requestZoomReset
673
675
  )
674
- self._imgOpts.sigSubsamplingChanged.connect(self._subsamplingChanged)
675
- self._mainWidget.sigUrlChanged.connect(self._urlChanged)
676
+ self._imgOpts.sigSubsamplingChanged.connect(self.sigSubsamplingChanged)
677
+ self._mainWidget.sigUrlChanged.connect(self.sigUrlChanged)
676
678
 
677
679
  # expose API
678
- self.getShiftStep = self._displacementSelector.getShiftStep
679
- self.setShiftStep = self._displacementSelector.setShiftStep
680
+ self.getShiftStep = self._displacementSelector.getStepSize
681
+ self.setShiftStep = self._displacementSelector.setStepSize
680
682
  self.sigRoiChanged = self._roiControl.sigRoiChanged
681
683
  self.sigAuto = self._shiftControl.sigAuto
682
684
  self.getROIOrigin = self._roiControl.getROIOrigin
@@ -696,12 +698,6 @@ class _AxisManual(qt.QWidget):
696
698
  def manual_uses_full_image(self, value):
697
699
  self._roiControl.manual_uses_full_image(value)
698
700
 
699
- def _urlChanged(self):
700
- self.sigUrlChanged.emit()
701
-
702
- def _subsamplingChanged(self):
703
- self.sigSubsamplingChanged.emit()
704
-
705
701
  def _incrementLeftShift(self):
706
702
  self._incrementShift("left")
707
703
 
@@ -843,7 +839,13 @@ class _AxisManualSelection(qt.QWidget):
843
839
  def __init__(self, parent, shift_mode):
844
840
  qt.QWidget.__init__(self, parent)
845
841
  self.setLayout(qt.QVBoxLayout())
846
- self._displacementSelector = _DisplacementSelector(parent=self)
842
+ self._displacementSelector = StepSizeSelectorWidget(
843
+ parent=self,
844
+ fine_value=0.1,
845
+ medium_value=1.0,
846
+ rough_value=None,
847
+ dtype=float,
848
+ )
847
849
  self.layout().addWidget(self._displacementSelector)
848
850
 
849
851
  self._shiftControl = _ShiftControl(parent=self, shift_mode=shift_mode)
@@ -856,10 +858,7 @@ class _AxisManualSelection(qt.QWidget):
856
858
  self.layout().addWidget(self._imgOpts)
857
859
 
858
860
  # connect signal / slot
859
- self._roiControl.sigResetZoomRequested.connect(self._requestZoomReset)
860
-
861
- def _requestZoomReset(self):
862
- self.sigResetZoomRequested.emit()
861
+ self._roiControl.sigResetZoomRequested.connect(self.sigResetZoomRequested)
863
862
 
864
863
 
865
864
  class _ROIControl(qt.QGroupBox):
@@ -895,8 +894,8 @@ class _ROIControl(qt.QGroupBox):
895
894
 
896
895
  # connect signal / Slot
897
896
  self._roiButton.toggled.connect(self._roiDefinition.setEnabled)
898
- self._fullImgButton.toggled.connect(self._requestZoomReset)
899
- self._roiButton.toggled.connect(self._requestZoomReset)
897
+ self._fullImgButton.toggled.connect(self.sigResetZoomRequested)
898
+ self._roiButton.toggled.connect(self.sigResetZoomRequested)
900
899
 
901
900
  # expose API
902
901
  self.sigRoiChanged = self._roiDefinition.sigRoiChanged
@@ -919,9 +918,6 @@ class _ROIControl(qt.QGroupBox):
919
918
  else:
920
919
  self._roiButton.setChecked(True)
921
920
 
922
- def _requestZoomReset(self):
923
- self.sigResetZoomRequested.emit()
924
-
925
921
 
926
922
  class _ROIDefinition(qt.QWidget):
927
923
  """
@@ -1165,12 +1161,39 @@ class _ShiftInformation(qt.QWidget):
1165
1161
  class _ShiftLineEdit(qt.QLineEdit):
1166
1162
  def __init__(self, *args, **kwargs):
1167
1163
  qt.QLineEdit.__init__(self, *args, **kwargs)
1164
+ self._defaultBackgroundColor = None
1165
+ # validator
1168
1166
  validator = qt.QDoubleValidator(parent=self, decimals=2)
1169
1167
  self.setValidator(validator)
1168
+ self._getDefaultBackgroundColor()
1169
+ # connect signal / slot
1170
+ self.textEdited.connect(self._userEditing)
1171
+ self.editingFinished.connect(self._userEndEditing)
1170
1172
 
1171
1173
  def sizeHint(self):
1172
1174
  return qt.QSize(40, 10)
1173
1175
 
1176
+ def _getDefaultBackgroundColor(self):
1177
+ if self._defaultBackgroundColor is None:
1178
+ self._defaultBackgroundColor = self.palette().color(
1179
+ self.backgroundRole()
1180
+ )
1181
+ return self._defaultBackgroundColor
1182
+
1183
+ def _userEditing(self, *args, **kwargs):
1184
+ palette = self.palette()
1185
+ palette.setColor(self.backgroundRole(), EDITING_BACKGROUND_COLOR)
1186
+ self.setPalette(palette)
1187
+
1188
+ def _userEndEditing(self, *args, **kwargs):
1189
+ print("user end editing")
1190
+ palette = self.palette()
1191
+ palette.setColor(
1192
+ self.backgroundRole(),
1193
+ self._getDefaultBackgroundColor(),
1194
+ )
1195
+ self.setPalette(palette)
1196
+
1174
1197
  sigShiftChanged = qt.Signal(float, float)
1175
1198
  """Signal emitted ony when xLE and yLE edition is finished"""
1176
1199
 
@@ -1213,69 +1236,6 @@ class _ShiftInformation(qt.QWidget):
1213
1236
  self.sigShiftChanged.emit(float(self._xLE.text()), float(self._yLE.text()))
1214
1237
 
1215
1238
 
1216
- class _DisplacementSelector(qt.QGroupBox):
1217
- """
1218
- Group box to define the displacement step value
1219
- """
1220
-
1221
- def __init__(self, parent):
1222
- qt.QGroupBox.__init__(self, "shift step", parent)
1223
- self.setLayout(qt.QVBoxLayout())
1224
- self._buttonGrp = qt.QButtonGroup(parent=self)
1225
- self._buttonGrp.setExclusive(True)
1226
-
1227
- self._rawButton = qt.QRadioButton("Rough (1 pixel)", parent=self)
1228
- self.layout().addWidget(self._rawButton)
1229
- self._buttonGrp.addButton(self._rawButton)
1230
-
1231
- self._fineButton = qt.QRadioButton("Fine (0.1 pixel)", parent=self)
1232
- self.layout().addWidget(self._fineButton)
1233
- self._buttonGrp.addButton(self._fineButton)
1234
-
1235
- self._manualWidget = qt.QWidget(parent=self)
1236
- self._manualWidget.setLayout(qt.QHBoxLayout())
1237
- self._manualWidget.layout().setContentsMargins(0, 0, 0, 0)
1238
- self._manualWidget.layout().setSpacing(0)
1239
- self._manualButton = qt.QRadioButton("Manual", parent=self._manualWidget)
1240
- self._manualWidget.layout().addWidget(self._manualButton)
1241
- self._manualLE = qt.QLineEdit("0.5", parent=self._manualWidget)
1242
- validator = qt.QDoubleValidator(parent=self._manualLE, decimals=2)
1243
- validator.setBottom(0.0)
1244
- self._manualLE.setValidator(validator)
1245
- self._manualWidget.layout().addWidget(self._manualLE)
1246
-
1247
- self.layout().addWidget(self._manualWidget)
1248
- self._manualLE.setEnabled(False)
1249
- self._buttonGrp.addButton(self._manualButton)
1250
-
1251
- self._rawButton.setChecked(True)
1252
-
1253
- # signal / slot connection
1254
- self._manualButton.toggled.connect(self._manualLE.setEnabled)
1255
-
1256
- def getShiftStep(self):
1257
- """
1258
-
1259
- :return: displacement shift defined
1260
- :rtype: float
1261
- """
1262
- if self._rawButton.isChecked():
1263
- return 1.0
1264
- elif self._fineButton.isChecked():
1265
- return 0.1
1266
- else:
1267
- return float(self._manualLE.text())
1268
-
1269
- def setShiftStep(self, value):
1270
- """
1271
-
1272
- :param float value: shift step
1273
- """
1274
- assert type(value) is float
1275
- self._manualButton.setChecked(True)
1276
- self._manualLE.setText(str(value))
1277
-
1278
-
1279
1239
  class _AxisOptionsWidget(qt.QWidget):
1280
1240
  """GUI to tune the axis algorithm"""
1281
1241
 
@@ -1501,9 +1461,7 @@ class AxisTabWidget(qt.QTabWidget):
1501
1461
  self.getEstimatedCor = self._calculationWidget.getEstimatedCor
1502
1462
 
1503
1463
  # connect signal / slot
1504
- self._calculationWidget.sigLockModeChanged.connect(
1505
- self._propagateSigLockModeChanged
1506
- )
1464
+ self._calculationWidget.sigLockModeChanged.connect(self.sigLockModeChanged)
1507
1465
  self.sigModeChanged.connect(self._updatePossibleInput)
1508
1466
  self._inputWidget._sigUrlChanged.connect(self._urlChanged)
1509
1467
  # not very nice but very convenient to have the setting near at the same level
@@ -1526,9 +1484,6 @@ class AxisTabWidget(qt.QTabWidget):
1526
1484
  def _urlChanged(self):
1527
1485
  self.sigUrlChanged.emit()
1528
1486
 
1529
- def _propagateSigLockModeChanged(self, lock):
1530
- self.sigLockModeChanged.emit(lock)
1531
-
1532
1487
  def getMode(self):
1533
1488
  """Return algorithm to use for axis calculation"""
1534
1489
  return self._calculationWidget.getMode()
@@ -1608,6 +1563,7 @@ class _CalculationWidget(qt.QWidget):
1608
1563
  ),
1609
1564
  ("separator", None),
1610
1565
  (axis_mode.AxisMode.composite_coarse_to_fine, "A auto-Cor method"),
1566
+ (axis_mode.AxisMode.near, "Alias to composite_coarse_to_fine"),
1611
1567
  ("separator", None),
1612
1568
  (axis_mode.AxisMode.manual, "Enter or find manually the COR value"),
1613
1569
  ("separator", None),
@@ -1762,8 +1718,11 @@ class _CalculationWidget(qt.QWidget):
1762
1718
  with block_signals(self._axis_params):
1763
1719
  side = self.getSide()
1764
1720
  self._nearOptsWidget.setVisible(
1765
- mode == axis_mode.AxisMode.composite_coarse_to_fine
1766
- and side == "near"
1721
+ (
1722
+ mode is axis_mode.AxisMode.composite_coarse_to_fine
1723
+ and side == "near"
1724
+ )
1725
+ or (mode is axis_mode.AxisMode.near)
1767
1726
  )
1768
1727
  self._corOptsWidget.setVisible(
1769
1728
  mode
@@ -1784,6 +1743,7 @@ class _CalculationWidget(qt.QWidget):
1784
1743
  axis_mode.AxisMode.sliding_window_radios,
1785
1744
  axis_mode.AxisMode.sino_coarse_to_fine,
1786
1745
  axis_mode.AxisMode.composite_coarse_to_fine,
1746
+ axis_mode.AxisMode.near,
1787
1747
  )
1788
1748
  )
1789
1749
  if mode in (
@@ -1795,6 +1755,7 @@ class _CalculationWidget(qt.QWidget):
1795
1755
  axis_mode.AxisMode.sliding_window_radios,
1796
1756
  axis_mode.AxisMode.sino_coarse_to_fine,
1797
1757
  axis_mode.AxisMode.composite_coarse_to_fine,
1758
+ axis_mode.AxisMode.near,
1798
1759
  ):
1799
1760
  self._lockMethodPB.setVisible(True)
1800
1761
  else:
@@ -1807,6 +1768,7 @@ class _CalculationWidget(qt.QWidget):
1807
1768
  axis_mode.AxisMode.sliding_window_sinogram,
1808
1769
  axis_mode.AxisMode.sliding_window_radios,
1809
1770
  axis_mode.AxisMode.composite_coarse_to_fine,
1771
+ axis_mode.AxisMode.near,
1810
1772
  )
1811
1773
  self._sideWidget.setVisible(side_visible)
1812
1774
  if side_visible is True:
@@ -1823,6 +1785,7 @@ class _CalculationWidget(qt.QWidget):
1823
1785
  axis_mode.AxisMode.sliding_window_sinogram,
1824
1786
  axis_mode.AxisMode.sliding_window_radios,
1825
1787
  axis_mode.AxisMode.composite_coarse_to_fine,
1788
+ axis_mode.AxisMode.near,
1826
1789
  ):
1827
1790
  return
1828
1791
  else:
@@ -1836,8 +1799,12 @@ class _CalculationWidget(qt.QWidget):
1836
1799
  ):
1837
1800
  values.append("all")
1838
1801
 
1839
- if mode in (axis_mode.AxisMode.composite_coarse_to_fine,):
1802
+ if mode is axis_mode.AxisMode.composite_coarse_to_fine:
1840
1803
  values.append("near")
1804
+ elif mode is axis_mode.AxisMode.near:
1805
+ values = [
1806
+ "near",
1807
+ ]
1841
1808
 
1842
1809
  for value in values:
1843
1810
  self._sideCB.addItem(value)
@@ -1865,6 +1832,7 @@ class _CalculationWidget(qt.QWidget):
1865
1832
  axis_mode.AxisMode.sliding_window_radios,
1866
1833
  axis_mode.AxisMode.sino_coarse_to_fine,
1867
1834
  axis_mode.AxisMode.composite_coarse_to_fine,
1835
+ axis_mode.AxisMode.near,
1868
1836
  ):
1869
1837
  raise ValueError(
1870
1838
  "Unable to lock the current mode is not an automatic algorithm"
@@ -1878,6 +1846,7 @@ class _CalculationWidget(qt.QWidget):
1878
1846
  axis_mode.AxisMode.sliding_window_radios,
1879
1847
  axis_mode.AxisMode.sino_coarse_to_fine,
1880
1848
  axis_mode.AxisMode.composite_coarse_to_fine,
1849
+ axis_mode.AxisMode.near,
1881
1850
  ):
1882
1851
  raise ValueError("Unable to lock %s this is not a lockable mode")
1883
1852
 
@@ -1929,10 +1898,12 @@ class _CalculationWidget(qt.QWidget):
1929
1898
 
1930
1899
  def _sideChanged(self, *args, **kwargs):
1931
1900
  side = self.getSide()
1932
- self._axis_params.side = side
1901
+ if side not in ("", None):
1902
+ self._axis_params.side = side
1933
1903
  mode = self.getMode()
1934
1904
  self._nearOptsWidget.setVisible(
1935
- mode == axis_mode.AxisMode.composite_coarse_to_fine and side == "near"
1905
+ (mode is axis_mode.AxisMode.composite_coarse_to_fine and side == "near")
1906
+ or mode is axis_mode.AxisMode.near
1936
1907
  )
1937
1908
 
1938
1909
  def getCorOptions(self):
@@ -1982,6 +1953,7 @@ class _CalculationWidget(qt.QWidget):
1982
1953
  axis_mode.AxisMode.sliding_window_sinogram,
1983
1954
  axis_mode.AxisMode.sliding_window_radios,
1984
1955
  axis_mode.AxisMode.composite_coarse_to_fine,
1956
+ axis_mode.AxisMode.near,
1985
1957
  ):
1986
1958
  self._sideWidget.setVisible(True)
1987
1959
  else:
@@ -2503,9 +2475,22 @@ class _ManualFramesSelection(qt.QWidget):
2503
2475
  _logger.warning("no angles available, unable to get '+180°' frame")
2504
2476
  else:
2505
2477
  angle = float(self._frame1CB.currentText())
2506
- closest_180_angle = self._getClosestAssociatedAngle(
2478
+ # look for the closest 'associated' angle.
2479
+ # as the angles are not limited to [0-360] we need to check for any value.
2480
+ # if the angle is on the first part of the acquisition we expect to find it near angle +180
2481
+ # if it is on the second part (for 360 degree) we expect to find it on the first part (0-180)
2482
+ closest_pls_180_angle = self._getClosestAssociatedAngle(
2507
2483
  angle + 180.0, self._anglesAvailable
2508
2484
  )
2485
+ score_add = abs(closest_pls_180_angle - angle)
2486
+ closest_minus_180_angle = self._getClosestAssociatedAngle(
2487
+ angle - 180.0, self._anglesAvailable
2488
+ )
2489
+ score_sub = abs(closest_minus_180_angle - angle)
2490
+ if score_add >= score_sub:
2491
+ closest_180_angle = closest_pls_180_angle
2492
+ else:
2493
+ closest_180_angle = closest_minus_180_angle
2509
2494
  item_idx = self._frame2CB.findText(self._angleToStr(closest_180_angle))
2510
2495
  if item_idx < 0:
2511
2496
  _logger.error(f"Unable to find item for angle {closest_180_angle}")
@@ -36,7 +36,8 @@ from silx.gui import qt
36
36
  from silx.gui.dialog.DataFileDialog import DataFileDialog
37
37
  from silx.io.url import DataUrl
38
38
 
39
- from tomwer.core import settings, utils
39
+ from tomwer.core import settings
40
+ from tomwer.core.utils.lbsram import is_low_on_memory
40
41
  from tomwer.core.process.reconstruction.darkref.darkrefscopy import DarkRefsCopy
41
42
  from tomwer.gui.reconstruction.darkref.darkrefwidget import DarkRefWidget
42
43
  from tomwer.io.utils import get_default_directory
@@ -117,7 +118,7 @@ class DarkRefAndCopyWidget(DarkRefWidget):
117
118
  # Security: if lbs is full, skip requesting fir user ref
118
119
  if (
119
120
  settings.isOnLbsram(scanID)
120
- and utils.isLowOnMemory(settings.get_lbsram_path()) is True
121
+ and is_low_on_memory(settings.get_lbsram_path()) is True
121
122
  ):
122
123
  # if computer is running into low memory on lbsram skip it
123
124
  mess = (
@@ -34,7 +34,7 @@ import os
34
34
  from silx.gui import qt
35
35
 
36
36
  from tomwer.core.process.reconstruction.lamino.tofu import FFCWhen, getDark, getFlats
37
- from tomwer.core.utils import (
37
+ from tomwer.core.utils.spec import (
38
38
  getClosestEnergy,
39
39
  getDARK_N,
40
40
  getDim1Dim2,
@@ -325,9 +325,9 @@ class _AnglesWidget(qt.QWidget):
325
325
  self._spacerBot.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
326
326
  self.layout().addWidget(self._spacerBot)
327
327
 
328
- self._volAngleX.sigEdited.connect(self._haveBeenEdited)
329
- self._volAngleY.sigEdited.connect(self._haveBeenEdited)
330
- self._volAngleZ.sigEdited.connect(self._haveBeenEdited)
328
+ self._volAngleX.sigEdited.connect(self.sigAnglesEdited)
329
+ self._volAngleY.sigEdited.connect(self.sigAnglesEdited)
330
+ self._volAngleZ.sigEdited.connect(self.sigAnglesEdited)
331
331
 
332
332
  # aliases
333
333
  self.setVolumeAngleX = self._volAngleX.setAngle
@@ -337,9 +337,6 @@ class _AnglesWidget(qt.QWidget):
337
337
  self.getVolumeAngleY = self._volAngleY.getAngle
338
338
  self.getVolumeAngleZ = self._volAngleZ.getAngle
339
339
 
340
- def _haveBeenEdited(self):
341
- self.sigAnglesEdited.emit()
342
-
343
340
  def set(self, xAngle, yAngle, zAngle):
344
341
  self.blockSignals(True)
345
342
  self.setVolumeAngleX(xAngle)
@@ -39,7 +39,7 @@ from tomwer.core.process.reconstruction.nabu.castvolume import (
39
39
  RESCALE_MAX_PERCENTILE,
40
40
  RESCALE_MIN_PERCENTILE,
41
41
  )
42
- from tomwer.core.process.reconstruction.nabu.nabucommon import NabuOutputFileFormat
42
+ from tomwer.core.process.reconstruction.output import NabuOutputFileFormat
43
43
  from tomwer.gui.qlefilesystem import QLFileSystem
44
44
  from tomwer.gui.reconstruction.nabu.nabuconfig.output import QNabuFileFormatComboBox
45
45
  from nxtomomill.io.utils import convert_str_to_tuple
@@ -29,13 +29,13 @@ __date__ = "02/12/2021"
29
29
 
30
30
 
31
31
  from silx.gui import qt
32
- from tomoscan.esrf.scan.hdf5scan import ImageKey
32
+ from nxtomo.nxobject.nxdetector import ImageKey
33
33
 
34
- from tomwer.core.scan.hdf5scan import HDF5TomoScan
34
+ from tomwer.core.scan.nxtomoscan import NXtomoScan
35
35
  from tomwer.core.utils.nxtomoutils import get_n_series
36
36
 
37
37
 
38
- def check_dark_series(scan: HDF5TomoScan, logger=None, user_input: bool = True) -> bool:
38
+ def check_dark_series(scan: NXtomoScan, logger=None, user_input: bool = True) -> bool:
39
39
  """
40
40
  check:
41
41
  - if scan has computed_dark attached. If there is more than one then ask confirmation to the user to process the dataset
@@ -43,15 +43,15 @@ def check_dark_series(scan: HDF5TomoScan, logger=None, user_input: bool = True)
43
43
 
44
44
  ask confirmation for processing is done by a pop up dialog.
45
45
 
46
- :param HDF5TomoScan scan: scan to check
46
+ :param NXtomoScan scan: scan to check
47
47
  :param bool user_input: if True and if n series of flat is invalid then ask the user to confirm the processing. Else print a warning and refuse processing
48
48
 
49
49
  :return: True if processing can be done else False
50
50
  :note: user can 'force' the processing to be done
51
51
  """
52
- if not isinstance(scan, HDF5TomoScan):
52
+ if not isinstance(scan, NXtomoScan):
53
53
  raise TypeError(
54
- f"scan is expected to be an instance of {HDF5TomoScan} not a {type(scan)}"
54
+ f"scan is expected to be an instance of {NXtomoScan} not a {type(scan)}"
55
55
  )
56
56
  try:
57
57
  image_keys = scan.image_keys
@@ -82,13 +82,13 @@ def check_dark_series(scan: HDF5TomoScan, logger=None, user_input: bool = True)
82
82
  return True
83
83
 
84
84
 
85
- def check_flat_series(scan: HDF5TomoScan, logger, user_input: bool = True) -> bool:
85
+ def check_flat_series(scan: NXtomoScan, logger, user_input: bool = True) -> bool:
86
86
  """
87
87
  Insure the scan contains at least one serie of flat. Otherwise warn the user nabu will not be able to process
88
88
  """
89
- if not isinstance(scan, HDF5TomoScan):
89
+ if not isinstance(scan, NXtomoScan):
90
90
  raise TypeError(
91
- f"scan is expected to be an instance of {HDF5TomoScan} not a {type(scan)}"
91
+ f"scan is expected to be an instance of {NXtomoScan} not a {type(scan)}"
92
92
  )
93
93
  try:
94
94
  image_keys = scan.image_keys
@@ -22,17 +22,28 @@ class HelicalPrepareWeightsDouble(qt.QWidget):
22
22
  )
23
23
  self.layout().addWidget(self._outputFilePathQLE, 0, 2, 1, 1)
24
24
 
25
- # transition_width
26
- self._transitionWidthQDSP = qt.QLabel("transition width", self)
27
- self.layout().addWidget(self._transitionWidthQDSP, 1, 0, 1, 1)
28
- self._transitionWidthQDSP = qt.QDoubleSpinBox(self)
29
- self._transitionWidthQDSP.setRange(0.0, 99999999)
30
- self._transitionWidthQDSP.setValue(50.0)
31
- self._transitionWidthQDSP.setToolTip(
25
+ # transition_width_vertical
26
+ self._verticalTransitionWidthQDSP = qt.QLabel("transition width", self)
27
+ self.layout().addWidget(self._verticalTransitionWidthQDSP, 1, 0, 1, 1)
28
+ self._verticalTransitionWidthQDSP = qt.QDoubleSpinBox(self)
29
+ self._verticalTransitionWidthQDSP.setRange(0.0, 99999999)
30
+ self._verticalTransitionWidthQDSP.setValue(50.0)
31
+ self._verticalTransitionWidthQDSP.setToolTip(
32
32
  "the transition width is used to determine how the weights are apodised near the upper and lower border"
33
33
  )
34
34
  # TODO: improve tooltip of this
35
- self.layout().addWidget(self._transitionWidthQDSP, 1, 1, 1, 2)
35
+ self.layout().addWidget(self._verticalTransitionWidthQDSP, 1, 1, 1, 2)
36
+
37
+ # transition_width_vertical
38
+ self._horizontalTransitionWidthQDSP = qt.QLabel("transition width", self)
39
+ self.layout().addWidget(self._horizontalTransitionWidthQDSP, 1, 0, 1, 1)
40
+ self._horizontalTransitionWidthQDSP = qt.QDoubleSpinBox(self)
41
+ self._horizontalTransitionWidthQDSP.setRange(0.0, 99999999)
42
+ self._horizontalTransitionWidthQDSP.setValue(50.0)
43
+ self._horizontalTransitionWidthQDSP.setToolTip(
44
+ "the transition width is used to determine how the weights are apodised near the upper and lower border"
45
+ )
46
+ self.layout().addWidget(self._horizontalTransitionWidthQDSP, 1, 1, 1, 2)
36
47
 
37
48
  spacer = qt.QWidget(parent=self)
38
49
  spacer.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
@@ -40,7 +51,8 @@ class HelicalPrepareWeightsDouble(qt.QWidget):
40
51
 
41
52
  # connect signal / slot
42
53
  self._outputFilePathQLE.editingFinished.connect(self._changed)
43
- self._transitionWidthQDSP.valueChanged.connect(self._changed)
54
+ self._verticalTransitionWidthQDSP.valueChanged.connect(self._changed)
55
+ self._horizontalTransitionWidthQDSP.valueChanged.connect(self._changed)
44
56
 
45
57
  def _changed(self, *args, **kwargs):
46
58
  self.sigConfigChanged.emit()
@@ -48,7 +60,8 @@ class HelicalPrepareWeightsDouble(qt.QWidget):
48
60
  def getConfiguration(self) -> dict:
49
61
  return {
50
62
  "processes_file": self._outputFilePathQLE.text(),
51
- "transition_width": self._transitionWidthQDSP.value(),
63
+ "transition_width_vertical": self._verticalTransitionWidthQDSP.value(),
64
+ "transition_width_horizontal": self._horizontalTransitionWidthQDSP.value(),
52
65
  }
53
66
 
54
67
  def setConfiguration(self, config: dict):
@@ -56,6 +69,10 @@ class HelicalPrepareWeightsDouble(qt.QWidget):
56
69
  if processes_file is not None:
57
70
  self._outputFilePathQLE.setText(processes_file)
58
71
 
59
- transition_width = config.get("transition_width", None)
72
+ transition_width = config.get("transition_width_vertical", None)
73
+ if transition_width is not None:
74
+ self._verticalTransitionWidthQDSP.setValue(float(transition_width))
75
+
76
+ transition_width = config.get("transition_width_horizontal", None)
60
77
  if transition_width is not None:
61
- self._transitionWidthQDSP.setValue(float(transition_width))
78
+ self._horizontalTransitionWidthQDSP.setValue(float(transition_width))
@@ -30,10 +30,8 @@ __date__ = "11/02/2020"
30
30
 
31
31
  from typing import Union
32
32
 
33
- from tomwer.core.process.reconstruction.nabu.utils import (
34
- ConfigurationLevel,
35
- _NabuStages,
36
- )
33
+ from tomwer.core.process.reconstruction.nabu.utils import _NabuStages
34
+ from tomwer.gui.configuration.level import ConfigurationLevel
37
35
 
38
36
 
39
37
  class _FilteringObject: