tomwer 1.2.9__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 -4
  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.9.dist-info → tomwer-1.3.0a0.dist-info}/METADATA +39 -39
  239. {tomwer-1.2.9.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.9-py3.11-nspkg.pth → /tomwer-1.3.0a0-py3.11-nspkg.pth +0 -0
  249. {tomwer-1.2.9.dist-info → tomwer-1.3.0a0.dist-info}/LICENSE +0 -0
  250. {tomwer-1.2.9.dist-info → tomwer-1.3.0a0.dist-info}/WHEEL +0 -0
  251. {tomwer-1.2.9.dist-info → tomwer-1.3.0a0.dist-info}/entry_points.txt +0 -0
  252. {tomwer-1.2.9.dist-info → tomwer-1.3.0a0.dist-info}/namespace_packages.txt +0 -0
  253. {tomwer-1.2.9.dist-info → tomwer-1.3.0a0.dist-info}/top_level.txt +0 -0
@@ -41,7 +41,7 @@ from tomwer.core.process.reconstruction.nabu.nabuslices import NabuSliceMode
41
41
  from tomwer.core.scan.edfscan import EDFTomoScan
42
42
  from tomwer.core.scan.scanfactory import ScanFactory
43
43
  from tomwer.core.utils.scanutils import MockEDF
44
- from tomwer.tests.utils import UtilsTest
44
+ from tomwer.tests.datasets import TomwerCIDatasets
45
45
 
46
46
 
47
47
  class TestNabuDescUtils(unittest.TestCase):
@@ -51,7 +51,7 @@ class TestNabuDescUtils(unittest.TestCase):
51
51
  unittest.TestCase.setUp(self)
52
52
  self.top_dir = tempfile.mkdtemp()
53
53
  self.dataset = "scan_3_"
54
- data_test_dir = UtilsTest.getEDFDataset(self.dataset)
54
+ data_test_dir = TomwerCIDatasets.get_dataset(f"edf_datasets/{self.dataset}")
55
55
  scan_folder = os.path.join(self.top_dir, self.dataset)
56
56
  shutil.copytree(data_test_dir, scan_folder)
57
57
  self.scan = ScanFactory.create_scan_object(scan_folder)
@@ -73,7 +73,7 @@ class TestNabuIni(unittest.TestCase):
73
73
  def setUp(self) -> None:
74
74
  self.dataset = "scan_3_"
75
75
  self._root_dir = tempfile.mkdtemp()
76
- data_test_dir = UtilsTest.getEDFDataset(self.dataset)
76
+ data_test_dir = TomwerCIDatasets.get_dataset("edf_datasets/scan_3_")
77
77
  scan_folder = os.path.join(self._root_dir, self.dataset)
78
78
  shutil.copytree(data_test_dir, scan_folder)
79
79
  self.scan = EDFTomoScan(scan_folder)
@@ -356,7 +356,7 @@ class TestNabuAndAxis(unittest.TestCase):
356
356
  def setUp(self) -> None:
357
357
  self.dataset = "scan_3_"
358
358
  self._root_dir = tempfile.mkdtemp()
359
- data_test_dir = UtilsTest.getEDFDataset(self.dataset)
359
+ data_test_dir = TomwerCIDatasets.get_dataset("edf_datasets/scan_3_")
360
360
  scan_folder = os.path.join(self._root_dir, self.dataset)
361
361
  shutil.copytree(data_test_dir, scan_folder)
362
362
  self.scan = EDFTomoScan(scan_folder)
@@ -36,7 +36,7 @@ import numpy
36
36
  from tomoscan.normalization import Method
37
37
 
38
38
  from tomwer.core.process.reconstruction.normalization import normalization, params
39
- from tomwer.core.utils.scanutils import MockHDF5
39
+ from tomwer.core.utils.scanutils import MockNXtomo
40
40
 
41
41
 
42
42
  class TestNormalization(unittest.TestCase):
@@ -47,7 +47,7 @@ class TestNormalization(unittest.TestCase):
47
47
  def setUp(self) -> None:
48
48
  self.tempdir = tempfile.mkdtemp()
49
49
  dim = 100
50
- self.scan = MockHDF5(
50
+ self.scan = MockNXtomo(
51
51
  scan_path=self.tempdir,
52
52
  n_proj=2,
53
53
  n_ini_proj=2,
@@ -48,7 +48,7 @@ from tomoscan.esrf.identifier.edfidentifier import (
48
48
  )
49
49
  from tomoscan.esrf.scan.edfscan import EDFTomoScan as _tsEDFTomoScan
50
50
  from tomoscan.esrf.scan.utils import get_data
51
- from tomoscan.scanbase import FOV
51
+ from nxtomo.nxobject.nxdetector import FOV
52
52
 
53
53
  from tomwer.core.process.reconstruction.darkref.settings import (
54
54
  DARKHST_PREFIX,
@@ -85,6 +85,9 @@ class EDFTomoScanIdentifier(_EDFTomoScanIdentifier, DatasetIdentifier):
85
85
  """used for processview header tooltip for now"""
86
86
  return self.to_str()
87
87
 
88
+ def short_description(self) -> str:
89
+ return f"scan: {os.path.basename(os.path.basename(self.folder))} (EDF)"
90
+
88
91
 
89
92
  class EDFTomoScan(_tsEDFTomoScan, TomwerScanBase):
90
93
  """
@@ -1,507 +1,26 @@
1
- # coding: utf-8
2
- # /*##########################################################################
3
- # Copyright (C) 2016 European Synchrotron Radiation Facility
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
- #
23
- #############################################################################*/
1
+ from tomwer.core.scan.nxtomoscan import NXtomoScanIdentifier, NXtomoScan
2
+ from tomwer.core.utils.deprecation import deprecated_warning
24
3
 
25
4
 
26
- __authors__ = ["H.Payno"]
27
- __license__ = "MIT"
28
- __date__ = "09/08/2018"
29
-
30
-
31
- import functools
32
- import io
33
- import json
34
- import logging
35
- import os
36
- import pathlib
37
- from datetime import datetime
38
- from typing import Optional
39
- from urllib.parse import urlparse
40
-
41
- import h5py
42
- from processview.core.dataset import DatasetIdentifier
43
- from tomoscan.esrf.identifier.hdf5Identifier import (
44
- HDF5TomoScanIdentifier as _HDF5TomoScanIdentifier,
45
- )
46
- from tomoscan.esrf.identifier.url_utils import UrlSettings, split_path, split_query
47
- from tomoscan.esrf.scan.hdf5scan import HDF5TomoScan as _tsHDF5TomoScan
48
- from tomoscan.esrf.scan.hdf5scan import ImageKey
49
- from tomoscan.io import HDF5File
50
-
51
- from tomwer.utils import docstring
52
- from tomwer.core.scan.helicalmetadata import HelicalMetadata
53
-
54
- from .scanbase import TomwerScanBase
55
-
56
- _logger = logging.getLogger(__name__)
57
-
58
-
59
- class HDF5TomoScanIdentifier(_HDF5TomoScanIdentifier, DatasetIdentifier):
5
+ class HDF5TomoScanIdentifier(NXtomoScanIdentifier):
60
6
  def __init__(self, metadata=None, *args, **kwargs):
61
- super().__init__(*args, **kwargs)
62
- DatasetIdentifier.__init__(
63
- self, data_builder=HDF5TomoScan.from_identifier, metadata=metadata
64
- )
65
-
66
- @staticmethod
67
- def from_str(identifier):
68
- info = urlparse(identifier)
69
- paths = split_path(info.path)
70
- if len(paths) == 1:
71
- hdf5_file = paths[0]
72
- tomo_type = None
73
- elif len(paths) == 2:
74
- tomo_type, hdf5_file = paths
75
- else:
76
- raise ValueError("Failed to parse path string:", info.path)
77
- if tomo_type is not None and tomo_type != HDF5TomoScanIdentifier.TOMO_TYPE:
78
- raise TypeError(
79
- f"provided identifier fits {tomo_type} and not {HDF5TomoScanIdentifier.TOMO_TYPE}"
80
- )
81
-
82
- queries = split_query(info.query)
83
- entry = queries.get(UrlSettings.DATA_PATH_KEY, None)
84
- if entry is None:
85
- raise ValueError(f"expects to get {UrlSettings.DATA_PATH_KEY} query")
86
-
87
- return HDF5TomoScanIdentifier(
88
- object=HDF5TomoScan, hdf5_file=hdf5_file, entry=entry
7
+ deprecated_warning(
8
+ name="tomwer.core.scan.nxtomoscan.NXtomoScanIdentifier",
9
+ type_="class",
10
+ reason="improve readibility",
11
+ since_version="1.3",
12
+ replacement="VolumeSymbolicLinkTask",
89
13
  )
14
+ super().__init__(metadata, *args, **kwargs)
90
15
 
91
- def long_description(self) -> str:
92
- """used for processview header tooltip for now"""
93
- return self.to_str()
94
-
95
-
96
- class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
97
- """
98
- This is the implementation of a TomoBase class for an acquisition stored
99
- in a HDF5 file.
100
-
101
- For now several property of the acquisition is accessible thought a getter
102
- (like get_scan_range) and a property (scan_range).
103
-
104
- This is done to be compliant with TomoBase instanciation. But his will be
105
- replace progressively by properties at the 'TomoBase' level
106
-
107
- :param scan: scan directory or scan masterfile.h5
108
- :type: Union[str,None]
109
- """
110
-
111
- _TYPE = "hdf5"
112
16
 
17
+ class HDF5TomoScan(NXtomoScan):
113
18
  def __init__(self, scan, entry, index=None, overwrite_proc_file=False):
114
- TomwerScanBase.__init__(self)
115
- _tsHDF5TomoScan.__init__(self, scan=scan, entry=entry, index=index)
116
- # register at least the 'default' working directory as a possible reconstruction path
117
- self.add_reconstruction_path(self.path)
118
- self._helical = HelicalMetadata()
119
-
120
- self._reconstruction_urls = None
121
- self._projections_with_angles = None
122
- self._process_file = self.get_process_file_name(self)
123
- self._init_index_process_file(overwrite_proc_file=overwrite_proc_file)
124
- try:
125
- reduced_darks, metadata = self.load_reduced_darks(return_info=True)
126
- except (KeyError, OSError, ValueError):
127
- # file or key does not exists
128
- pass
129
- else:
130
- self.set_reduced_darks(reduced_darks, darks_infos=metadata)
131
-
132
- try:
133
- reduced_flats, metadata = self.load_reduced_flats(return_info=True)
134
- except (KeyError, OSError, ValueError):
135
- pass
136
- else:
137
- self.set_reduced_flats(reduced_flats, flats_infos=metadata)
138
-
139
- @property
140
- def working_directory(self):
141
- if self.master_file is None:
142
- return None
143
- else:
144
- return os.path.realpath(os.path.dirname(self.master_file))
145
-
146
- @property
147
- def helical(self):
148
- return self._helical
149
-
150
- @staticmethod
151
- def from_identifier(identifier):
152
- """Return the Dataset from a identifier"""
153
- if not isinstance(identifier, HDF5TomoScanIdentifier):
154
- raise TypeError(
155
- f"identifier should be an instance of {HDF5TomoScanIdentifier}. Not {type(identifier)}"
156
- )
157
- return HDF5TomoScan(scan=identifier.file_path, entry=identifier.data_path)
158
-
159
- def get_identifier(self):
160
- try:
161
- stat = pathlib.Path(self.master_file).stat()
162
- except Exception:
163
- stat = None
164
-
165
- return HDF5TomoScanIdentifier(
166
- object=self,
167
- hdf5_file=self.master_file,
168
- entry=self.entry,
169
- metadata={
170
- "name": self.master_file,
171
- "creation_time": datetime.fromtimestamp(stat.st_ctime)
172
- if stat
173
- else None,
174
- "modification_time": datetime.fromtimestamp(stat.st_ctime)
175
- if stat
176
- else None,
177
- },
178
- )
179
-
180
- @staticmethod
181
- def get_process_file_name(scan):
182
- if scan.path is not None:
183
- basename, _ = os.path.splitext(scan.master_file)
184
- basename = os.path.basename(basename)
185
- basename = "_".join((basename, "tomwer_processes.h5"))
186
- return os.path.join(scan.path, basename)
187
- else:
188
- return None
189
-
190
- @staticmethod
191
- def directory_contains_scan(directory, src_pattern=None, dest_pattern=None):
192
- """
193
-
194
- Check if the given directory is holding an acquisition
195
-
196
- :param str directory: directory we want to check
197
- :param str src_pattern: buffer name pattern ('lbsram')
198
- :param dest_pattern: output pattern (''). Needed because some
199
- acquisition can split the file produce between
200
- two directories. This is the case for edf,
201
- where .info file are generated in /data/dir
202
- instead of /lbsram/data/dir
203
- :type: str
204
- :return: does the given directory contains any acquisition
205
- :rtype: bool
206
- """
207
- master_file = os.path.join(directory, os.path.basename(directory))
208
- if os.path.exists("master_file.hdf5"):
209
- return True
210
- else:
211
- return os.path.exists(master_file + ".h5")
212
-
213
- def clear_caches(self):
214
- _tsHDF5TomoScan.clear_caches(self)
215
- TomwerScanBase.clear_caches(self)
216
-
217
- def is_abort(self, src_pattern, dest_pattern):
218
- """
219
- Check if the acquisition have been aborted. In this case the directory
220
- should contain a [scan].abo file
221
-
222
- :param str src_pattern: buffer name pattern ('lbsram')
223
- :param dest_pattern: output pattern (''). Needed because some
224
- acquisition can split the file produce between
225
- two directories. This is the case for edf,
226
- where .info file are generated in /data/dir
227
- instead of /lbsram/data/dir
228
- :return: True if the acquisition have been abort and the directory
229
- should be abort
230
- """
231
- # for now there is no abort definition in .hdf5
232
- return False
233
-
234
- @staticmethod
235
- def from_dict(_dict):
236
- path = _dict[HDF5TomoScan.DICT_PATH_KEY]
237
- entry = _dict[HDF5TomoScan._DICT_ENTRY_KEY]
238
-
239
- scan = HDF5TomoScan(scan=path, entry=entry)
240
- scan.load_from_dict(_dict=_dict)
241
- return scan
242
-
243
- @docstring(TomwerScanBase)
244
- def load_from_dict(self, _dict):
245
- """
246
-
247
- :param _dict:
248
- :return:
249
- """
250
- if isinstance(_dict, io.TextIOWrapper):
251
- data = json.load(_dict)
252
- else:
253
- data = _dict
254
- if not (self.DICT_TYPE_KEY in data and data[self.DICT_TYPE_KEY] == self._TYPE):
255
- raise ValueError("Description is not an EDFScan json description")
256
-
257
- _tsHDF5TomoScan.load_from_dict(self, _dict)
258
- TomwerScanBase.load_from_dict(self, _dict)
259
- return self
260
-
261
- @docstring(TomwerScanBase)
262
- def to_dict(self) -> dict:
263
- ddict = _tsHDF5TomoScan.to_dict(self)
264
- ddict.update(TomwerScanBase.to_dict(self))
265
- return ddict
266
-
267
- def update(self):
268
- """update list of radio and reconstruction by parsing the scan folder"""
269
- if self.master_file is None:
270
- return
271
- if not os.path.exists(self.master_file):
272
- return
273
- _tsHDF5TomoScan.update(self)
274
- self.reconstructions = self.get_reconstructions_urls()
275
-
276
- def _get_scheme(self):
277
- """
278
-
279
- :return: scheme to read url
280
- :rtype: str
281
- """
282
- return "silx"
283
-
284
- def is_finish(self):
285
- return len(self.projections) >= self.tomo_n
286
-
287
- @docstring(TomwerScanBase.get_sinogram)
288
- @functools.lru_cache(maxsize=16, typed=True)
289
- def get_sinogram(self, line, subsampling=1, norm_method=None, **kwargs):
290
- """
291
-
292
- extract the sinogram from projections
293
-
294
- :param line: which sinogram we want
295
- :type: int
296
- :param subsampling: subsampling to apply if any. Allows to skip some io
297
- :type: int
298
- :return: sinogram from the radio lines
299
- :rtype: numpy.array
300
- """
301
- return _tsHDF5TomoScan.get_sinogram(
302
- self,
303
- line=line,
304
- subsampling=subsampling,
305
- norm_method=norm_method,
306
- **kwargs,
307
- )
308
-
309
- @docstring(TomwerScanBase.get_proj_angle_url)
310
- def get_proj_angle_url(self, use_cache: bool = True, with_alignment=True):
311
- if not use_cache:
312
- self._cache_proj_urls = None
313
-
314
- if self._cache_proj_urls is None:
315
- frames = self.frames
316
- if frames is None:
317
- return {}
318
-
319
- self._cache_proj_urls = {}
320
- for frame in frames:
321
- if frame.image_key is ImageKey.PROJECTION:
322
- if frame.is_control and with_alignment:
323
- self._cache_proj_urls[f"{frame.rotation_angle} (1)"] = frame.url
324
- elif frame.is_control:
325
- continue
326
- else:
327
- self._cache_proj_urls[str(frame.rotation_angle)] = frame.url
328
- return self._cache_proj_urls
329
-
330
- @docstring(TomwerScanBase._deduce_transfert_scan)
331
- def _deduce_transfert_scan(self, output_dir):
332
- new_master_file_path = os.path.join(
333
- output_dir, os.path.basename(self.master_file)
334
- )
335
- return HDF5TomoScan(scan=new_master_file_path, entry=self.entry)
336
-
337
- def data_flat_field_correction(self, data, index=None):
338
- flats = self.reduced_flats
339
- flat1 = flat2 = None
340
- index_flat1 = index_flat2 = None
341
- if flats is not None:
342
- flat_indexes = sorted(list(flats.keys()))
343
- if len(flats) > 0:
344
- index_flat1 = flat_indexes[0]
345
- flat1 = flats[index_flat1]
346
- if len(flats) > 1:
347
- index_flat2 = flat_indexes[-1]
348
- flat2 = flats[index_flat2]
349
- darks = self.reduced_darks
350
- dark = None
351
- if darks is not None and len(darks) > 0:
352
- # take only one dark into account for now
353
- dark = list(darks.values())[0]
354
- return self._flat_field_correction(
355
- data=data,
356
- dark=dark,
357
- flat1=flat1,
358
- flat2=flat2,
359
- index_flat1=index_flat1,
360
- index_flat2=index_flat2,
361
- index_proj=index,
362
- )
363
-
364
- @docstring(_tsHDF5TomoScan.ff_interval)
365
- @property
366
- def ff_interval(self):
367
- """
368
- Make some assumption to compute the flat field interval:
369
- """
370
-
371
- def get_first_two_ff_indexes():
372
- if self.flats is None:
373
- return None, None
374
- else:
375
- self._last_flat_index = None
376
- self._first_serie_flat_index = None
377
- for flat_index in self.flats:
378
- if self._last_flat_index is None:
379
- self._last_flat_index = flat_index
380
- elif flat_index == self._last_flat_index + 1:
381
- self._last_flat_index = flat_index
382
- continue
383
- else:
384
- return self._last_flat_index, flat_index
385
- return None, None
386
-
387
- first_serie_index, second_serie_index = get_first_two_ff_indexes()
388
- if first_serie_index is None:
389
- return 0
390
- elif second_serie_index is not None:
391
- return second_serie_index - first_serie_index - 1
392
- else:
393
- return 0
394
-
395
- def projections_with_angle(self):
396
- """projections / radio, does not include the return projections"""
397
- if self._projections_with_angles is None:
398
- if self.frames:
399
- proj_frames = tuple(
400
- filter(
401
- lambda x: x.image_key == ImageKey.PROJECTION
402
- and x.is_control is False,
403
- self.frames,
404
- )
405
- )
406
- self._projections_with_angles = {}
407
- for proj_frame in proj_frames:
408
- self._projections_with_angles[
409
- proj_frame.rotation_angle
410
- ] = proj_frame.url
411
- return self._projections_with_angles
412
-
413
- @staticmethod
414
- def is_nexus_nxtomo_file(file_path: str) -> bool:
415
- if h5py.is_hdf5(file_path):
416
- return len(HDF5TomoScan.get_nxtomo_entries(file_path)) > 0
417
-
418
- @staticmethod
419
- def get_nxtomo_entries(file_path: str) -> tuple:
420
- if not h5py.is_hdf5(file_path):
421
- return tuple()
422
- else:
423
- res = []
424
- with HDF5File(file_path, mode="r", swmr=True, libver="latest") as h5s:
425
- for entry_name, node in h5s.items():
426
- if isinstance(node, h5py.Group):
427
- if HDF5TomoScan.entry_is_nx_tomo(node):
428
- res.append(entry_name)
429
- return tuple(res)
430
-
431
- @staticmethod
432
- def entry_is_nx_tomo(entry: h5py.Group):
433
- return ("beam" in entry and "instrument" in entry and "sample" in entry) or (
434
- hasattr(entry, "attrs")
435
- and "definition" in entry.attrs
436
- and entry.attrs["definition"] == "NXtomo"
437
- )
438
-
439
- @staticmethod
440
- def is_nxdetector(grp: h5py.Group):
441
- """
442
- Check if the grp is an nx detector
443
-
444
- :param h5py.Group grp:
445
- :return: True if this is the definition of a group
446
- :rtype: bool
447
- """
448
- if hasattr(grp, "attrs"):
449
- if "NX_class" in grp.attrs and grp.attrs["NX_class"] == "NXdetector":
450
- return True
451
- return False
452
-
453
- # Dataset implementation
454
-
455
- @docstring(TomwerScanBase)
456
- def get_nabu_dataset_info(self, binning=1, binning_z=1, proj_subsampling=1):
457
- if not isinstance(binning, int):
458
- raise TypeError(f"binning should be an int. Not {type(binning)}")
459
- if not isinstance(binning_z, int):
460
- raise TypeError(f"binning_z should be an int. Not {type(binning_z)}")
461
- if not isinstance(proj_subsampling, int):
462
- raise TypeError(
463
- f"proj_subsampling should be an int. Not {type(proj_subsampling)}"
464
- )
465
- return {
466
- "hdf5_entry": self.entry,
467
- "location": os.path.basename(self.master_file),
468
- "binning": binning,
469
- "binning_z": binning_z,
470
- "projections_subsampling": proj_subsampling,
471
- }
472
-
473
- @docstring(TomwerScanBase)
474
- def to_nabu_dataset_analyser(self):
475
- from nabu.resources.dataset_analyzer import HDF5DatasetAnalyzer
476
-
477
- return HDF5DatasetAnalyzer(
478
- location=self.master_file, extra_options={"hdf5_entry": self.entry}
479
- )
480
-
481
- @docstring(TomwerScanBase)
482
- def scan_dir_name(self) -> Optional[str]:
483
- """for 'this/is/my/file.h5' returns 'my'"""
484
- if self.master_file is not None:
485
- return os.path.dirname(self.master_file).split(os.sep)[-1]
486
- else:
487
- return None
488
-
489
- @docstring(TomwerScanBase)
490
- def scan_basename(self):
491
- if self.master_file is not None:
492
- try:
493
- return os.path.dirname(self.master_file)
494
- except Exception:
495
- return None
496
- else:
497
- return None
498
-
499
- @docstring(TomwerScanBase)
500
- def scan_parent_dir_basename(self):
501
- if self.master_file is not None:
502
- try:
503
- return os.path.dirname(os.path.dirname(self.master_file))
504
- except Exception:
505
- return None
506
- else:
507
- return None
19
+ deprecated_warning(
20
+ name="tomwer.core.scan.nxtomoscan.NXtomoScan",
21
+ type_="class",
22
+ reason="improve readibility",
23
+ since_version="1.3",
24
+ replacement="VolumeSymbolicLinkTask",
25
+ )
26
+ super().__init__(scan, entry, index, overwrite_proc_file)