tomwer 1.0.4__py3-none-any.whl → 1.1.0__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 (256) hide show
  1. orangecontrib/tomwer/tutorials/EBS_tomo_listener.ows +39 -0
  2. orangecontrib/tomwer/tutorials/cast_volume.ows +34 -0
  3. orangecontrib/tomwer/tutorials/simple_slice_reconstruction.ows +39 -0
  4. orangecontrib/tomwer/tutorials/simple_volume_local_reconstruction.ows +49 -0
  5. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +59 -0
  6. orangecontrib/tomwer/tutorials/using_saaxis_to_find_cor.ows +44 -0
  7. orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +1 -1
  8. orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +14 -4
  9. orangecontrib/tomwer/widgets/cluster/__init__.py +1 -1
  10. orangecontrib/tomwer/widgets/control/DataListOW.py +12 -5
  11. orangecontrib/tomwer/widgets/control/DataListenerOW.py +18 -9
  12. orangecontrib/tomwer/widgets/control/DataSelectorOW.py +13 -6
  13. orangecontrib/tomwer/widgets/control/DataTransfertOW.py +4 -5
  14. orangecontrib/tomwer/widgets/control/DataValidatorOW.py +8 -4
  15. orangecontrib/tomwer/widgets/control/DataWatcherOW.py +4 -6
  16. orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +49 -62
  17. orangecontrib/tomwer/widgets/control/FilterOW.py +2 -4
  18. orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +93 -0
  19. orangecontrib/tomwer/widgets/control/NXTomomillOW.py +135 -128
  20. orangecontrib/tomwer/widgets/control/NotifierOW.py +31 -7
  21. orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +3 -5
  22. orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +85 -0
  23. orangecontrib/tomwer/widgets/control/VolumeSelector.py +12 -4
  24. orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +11 -7
  25. orangecontrib/tomwer/widgets/control/icons/notification.svg +4 -4
  26. orangecontrib/tomwer/widgets/control/icons/nxtomomill.png +0 -0
  27. orangecontrib/tomwer/widgets/control/icons/nxtomomill.svg +8 -5
  28. orangecontrib/tomwer/widgets/control/icons/tomoobjserie.png +0 -0
  29. orangecontrib/tomwer/widgets/control/icons/tomoobjserie.svg +138 -0
  30. orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +16 -4
  31. orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +100 -0
  32. orangecontrib/tomwer/widgets/edit/icons/image_key_editor.png +0 -0
  33. orangecontrib/tomwer/widgets/edit/icons/image_key_upgrader.png +0 -0
  34. orangecontrib/tomwer/widgets/edit/icons/nx_tomo_editor.png +0 -0
  35. orangecontrib/tomwer/widgets/edit/icons/nx_tomo_editor.svg +123 -0
  36. orangecontrib/tomwer/widgets/edit/test/test_dark_flat_patch.py +21 -1
  37. orangecontrib/tomwer/widgets/edit/test/test_image_key_editor.py +1 -1
  38. orangecontrib/tomwer/widgets/edit/test/test_image_key_upgrader.py +1 -1
  39. orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +25 -0
  40. orangecontrib/tomwer/widgets/other/PythonScriptOW.py +19 -10
  41. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +20 -14
  42. orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +24 -10
  43. orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +26 -21
  44. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +29 -12
  45. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +44 -17
  46. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +28 -18
  47. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +24 -17
  48. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +6 -6
  49. orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +4 -2
  50. orangecontrib/tomwer/widgets/reconstruction/icons/nabu_2d.png +0 -0
  51. orangecontrib/tomwer/widgets/reconstruction/icons/nabu_2d.svg +11 -8
  52. orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +10 -4
  53. orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
  54. orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +69 -0
  55. orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +2 -4
  56. orangecontrib/tomwer/widgets/visualization/icons/nx_tomo_metadata_viewer.png +0 -0
  57. orangecontrib/tomwer/widgets/visualization/icons/nx_tomo_metadata_viewer.svg +105 -0
  58. tomwer/__main__.py +10 -5
  59. tomwer/app/canvas_launcher/config.py +10 -10
  60. tomwer/app/canvas_launcher/mainwindow.py +68 -6
  61. tomwer/app/canvas_launcher/widgetsscheme.py +1 -3
  62. tomwer/app/darkref.py +16 -12
  63. tomwer/app/imagekeyeditor.py +2 -2
  64. tomwer/app/imagekeyupgrader.py +104 -0
  65. tomwer/app/nxtomoeditor.py +103 -0
  66. tomwer/app/rsync.py +1 -1
  67. tomwer/core/cluster/cluster.py +1 -1
  68. tomwer/core/futureobject.py +1 -0
  69. tomwer/core/process/control/datalistener/datalistener.py +7 -1
  70. tomwer/core/process/control/datalistener/rpcserver.py +3 -3
  71. tomwer/core/process/control/datawatcher/datawatcher.py +18 -18
  72. tomwer/core/process/control/datawatcher/datawatcherobserver.py +5 -8
  73. tomwer/core/process/control/datawatcher/datawatcherprocess.py +2 -3
  74. tomwer/core/process/control/datawatcher/edfdwprocess.py +2 -2
  75. tomwer/core/process/control/nxtomomill.py +33 -58
  76. tomwer/core/process/control/scanlist.py +2 -1
  77. tomwer/core/process/control/scanselector.py +7 -0
  78. tomwer/core/process/control/scantransfer.py +9 -18
  79. tomwer/core/process/control/scanvalidator.py +6 -5
  80. tomwer/core/process/control/singletomoobj.py +2 -1
  81. tomwer/core/process/control/timer.py +2 -1
  82. tomwer/core/process/control/tomoobjserie.py +8 -0
  83. tomwer/core/process/control/volumeselector.py +2 -1
  84. tomwer/core/process/control/volumesymlink.py +2 -1
  85. tomwer/core/process/edit/darkflatpatch.py +2 -1
  86. tomwer/core/process/edit/imagekeyeditor.py +4 -3
  87. tomwer/core/process/reconstruction/axis/axis.py +29 -32
  88. tomwer/core/process/reconstruction/axis/mode.py +3 -2
  89. tomwer/core/process/reconstruction/axis/params.py +35 -16
  90. tomwer/core/process/reconstruction/darkref/darkrefs.py +90 -707
  91. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +44 -16
  92. tomwer/core/process/reconstruction/darkref/params.py +62 -67
  93. tomwer/core/process/reconstruction/lamino/tofu.py +1 -1
  94. tomwer/core/process/reconstruction/nabu/castvolume.py +21 -26
  95. tomwer/core/process/reconstruction/nabu/nabucommon.py +36 -38
  96. tomwer/core/process/reconstruction/nabu/nabuscores.py +28 -13
  97. tomwer/core/process/reconstruction/nabu/nabuslices.py +41 -14
  98. tomwer/core/process/reconstruction/nabu/nabuvolume.py +21 -12
  99. tomwer/core/process/reconstruction/nabu/utils.py +12 -1
  100. tomwer/core/process/reconstruction/normalization/normalization.py +9 -8
  101. tomwer/core/process/reconstruction/saaxis/saaxis.py +46 -20
  102. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +38 -12
  103. tomwer/core/process/reconstruction/test/__init__.py +0 -39
  104. tomwer/core/process/reconstruction/test/test_axis_params.py +25 -3
  105. tomwer/core/process/reconstruction/test/test_darkref_copy.py +117 -1
  106. tomwer/core/process/script/python.py +16 -12
  107. tomwer/core/process/task.py +3 -7
  108. tomwer/core/process/test/test_axis.py +1 -1
  109. tomwer/core/process/test/test_dark_and_flat.py +41 -111
  110. tomwer/core/process/test/test_data_listener.py +0 -29
  111. tomwer/core/process/test/test_data_transfer.py +10 -14
  112. tomwer/core/process/test/test_nabu.py +1 -1
  113. tomwer/core/process/test/test_normalization.py +1 -1
  114. tomwer/core/process/visualization/liveslice.py +6 -0
  115. tomwer/core/scan/blissscan.py +37 -2
  116. tomwer/core/scan/edfscan.py +14 -4
  117. tomwer/core/scan/hdf5scan.py +10 -4
  118. tomwer/core/scan/scanbase.py +35 -29
  119. tomwer/core/scan/scanfactory.py +3 -17
  120. tomwer/core/scan/test/test_h5.py +1 -1
  121. tomwer/core/scan/test/test_process_registration.py +0 -11
  122. tomwer/core/scan/test/test_scan.py +32 -30
  123. tomwer/core/settings.py +2 -2
  124. tomwer/core/test/test_utils.py +1 -1
  125. tomwer/core/tomwer_object.py +19 -0
  126. tomwer/core/utils/__init__.py +0 -45
  127. tomwer/core/utils/char.py +2 -0
  128. tomwer/core/utils/gpu.py +5 -5
  129. tomwer/core/utils/nxtomoutils.py +2 -2
  130. tomwer/core/utils/scanutils.py +50 -0
  131. tomwer/core/utils/volumeutils.py +13 -0
  132. tomwer/core/volume/edfvolume.py +4 -0
  133. tomwer/core/volume/hdf5volume.py +4 -0
  134. tomwer/core/volume/jp2kvolume.py +4 -0
  135. tomwer/core/volume/rawvolume.py +4 -0
  136. tomwer/core/volume/tiffvolume.py +4 -0
  137. tomwer/core/volume/volumebase.py +19 -12
  138. tomwer/core/volume/volumefactory.py +20 -1
  139. tomwer/gui/cluster/slurm.py +1 -1
  140. tomwer/gui/cluster/test/test_cluster.py +2 -2
  141. tomwer/gui/control/datalist.py +109 -34
  142. tomwer/gui/control/datatransfert.py +1 -1
  143. tomwer/gui/control/datawatcher/datawatcher.py +23 -13
  144. tomwer/gui/control/datawatcher/datawatcherobserver.py +1 -1
  145. tomwer/gui/control/observations.py +0 -3
  146. tomwer/gui/control/selectorwidgetbase.py +42 -11
  147. tomwer/gui/control/serie/seriecreator.py +967 -0
  148. tomwer/{web/__init__.py → gui/control/serie/seriewaiter.py} +5 -7
  149. tomwer/gui/control/singletomoobj.py +15 -3
  150. tomwer/gui/control/test/test_datalist.py +1 -1
  151. tomwer/gui/control/test/test_datalistener.py +1 -1
  152. tomwer/gui/control/test/test_inputwidget.py +1 -1
  153. tomwer/gui/control/test/test_process_manager.py +1 -13
  154. tomwer/gui/control/test/test_scanselector.py +1 -1
  155. tomwer/gui/control/test/test_scanvalidator.py +1 -1
  156. tomwer/gui/control/test/test_single_tomo_obj.py +1 -1
  157. tomwer/gui/control/test/test_volume_dialog.py +19 -7
  158. tomwer/gui/control/test/test_volumeselector.py +4 -4
  159. tomwer/gui/debugtools/datasetgenerator.py +1 -8
  160. tomwer/gui/edit/dkrfpatch.py +2 -2
  161. tomwer/gui/edit/imagekeyeditor.py +12 -9
  162. tomwer/gui/edit/nxtomoeditor.py +475 -0
  163. tomwer/gui/edit/test/test_dkrf_patch.py +2 -14
  164. tomwer/gui/edit/test/test_image_key_editor.py +2 -2
  165. tomwer/gui/edit/test/test_nx_editor.py +155 -0
  166. tomwer/gui/qfolderdialog.py +11 -0
  167. tomwer/gui/reconstruction/axis/CompareImages.py +27 -29
  168. tomwer/gui/reconstruction/axis/axis.py +2 -0
  169. tomwer/gui/reconstruction/axis/radioaxis.py +67 -11
  170. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +7 -9
  171. tomwer/gui/reconstruction/darkref/darkrefwidget.py +22 -24
  172. tomwer/gui/reconstruction/lamino/tofu/projections.py +1 -1
  173. tomwer/gui/reconstruction/lamino/tofu/tofu.py +3 -3
  174. tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +4 -4
  175. tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +10 -4
  176. tomwer/gui/reconstruction/nabu/castvolume.py +80 -11
  177. tomwer/gui/reconstruction/nabu/check.py +1 -1
  178. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +352 -0
  179. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +0 -9
  180. tomwer/gui/reconstruction/nabu/nabuconfig/output.py +1 -1
  181. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +18 -19
  182. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +30 -7
  183. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +26 -13
  184. tomwer/gui/reconstruction/nabu/slices.py +10 -2
  185. tomwer/gui/reconstruction/nabu/slurm.py +1 -1
  186. tomwer/gui/reconstruction/nabu/volume.py +13 -7
  187. tomwer/gui/reconstruction/normalization/intensity.py +1 -1
  188. tomwer/gui/reconstruction/saaxis/corrangeselector.py +10 -34
  189. tomwer/gui/reconstruction/saaxis/saaxis.py +11 -6
  190. tomwer/gui/reconstruction/saaxis/sliceselector.py +11 -26
  191. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +13 -8
  192. tomwer/gui/reconstruction/scores/scoreplot.py +67 -61
  193. tomwer/gui/reconstruction/test/test_axis.py +2 -2
  194. tomwer/gui/reconstruction/test/test_lamino.py +2 -2
  195. tomwer/gui/reconstruction/test/test_nabu.py +14 -1
  196. tomwer/gui/reconstruction/test/test_saaxis.py +8 -17
  197. tomwer/gui/reconstruction/test/test_sadeltabeta.py +7 -13
  198. tomwer/gui/stackplot.py +11 -28
  199. tomwer/gui/test/test_axis_gui.py +4 -4
  200. tomwer/gui/test/test_qfolder_dialog.py +12 -0
  201. tomwer/gui/utils/inputwidget.py +42 -21
  202. tomwer/gui/utils/lineselector/lineselector.py +13 -21
  203. tomwer/gui/utils/scandescription.py +2 -4
  204. tomwer/gui/utils/slider.py +1 -102
  205. tomwer/gui/utils/unitsystem.py +48 -11
  206. tomwer/gui/visualization/dataviewer.py +24 -17
  207. tomwer/gui/visualization/diffviewer/diffviewer.py +2 -11
  208. tomwer/gui/visualization/nxtomometadata.py +21 -0
  209. tomwer/gui/visualization/scanoverview.py +0 -1
  210. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +72 -0
  211. tomwer/gui/visualization/test/test_stacks.py +1 -1
  212. tomwer/gui/visualization/tomoobjoverview.py +49 -0
  213. tomwer/gui/visualization/volumeoverview.py +64 -0
  214. tomwer/gui/visualization/volumeviewer.py +1 -1
  215. tomwer/resources/gui/icons/multi-document-save.png +0 -0
  216. tomwer/resources/gui/icons/multi-document-save.svg +101 -0
  217. tomwer/resources/gui/illustrations/ctf_z1.png +0 -0
  218. tomwer/resources/gui/illustrations/ctf_z1.svg +471 -0
  219. tomwer/synctools/datalistener.py +5 -1
  220. tomwer/synctools/imageloaderthread.py +2 -2
  221. tomwer/synctools/stacks/edit/imagekeyeditor.py +1 -1
  222. tomwer/synctools/stacks/processingstack.py +2 -2
  223. tomwer/synctools/stacks/reconstruction/castvolume.py +1 -0
  224. tomwer/synctools/stacks/reconstruction/lamino.py +1 -3
  225. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +0 -2
  226. tomwer/synctools/test/test_darkRefs.py +32 -149
  227. tomwer/synctools/test/test_foldertransfer.py +1 -1
  228. tomwer/synctools/test/test_scanstages.py +2 -2
  229. tomwer/tests/__init__.py +0 -0
  230. tomwer/tests/conftest.py +51 -0
  231. tomwer/{test → tests}/test_scripts.py +1 -1
  232. tomwer/tests/test_utils.py +10 -0
  233. tomwer/{test → tests}/utils/utilstest.py +0 -11
  234. tomwer/version.py +3 -3
  235. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/METADATA +14 -16
  236. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/RECORD +245 -217
  237. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/WHEEL +1 -1
  238. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/entry_points.txt +6 -0
  239. orangecontrib/tomwer/setup.py +0 -45
  240. orangecontrib/tomwer/widgets/setup.py +0 -49
  241. tomwer/app/process.py +0 -153
  242. tomwer/core/process/reconstruction/nabu/slurm.py +0 -36
  243. tomwer/core/process/reconstruction/utils/nabu_slice_exec.py +0 -10
  244. tomwer/core/utils/laminoutils.py +0 -80
  245. tomwer/gui/utils/lineselector/lineselection.py +0 -76
  246. tomwer/setup.py +0 -52
  247. tomwer/web/client.py +0 -43
  248. tomwer/web/config.py +0 -36
  249. tomwer/web/test/test_graylog_connection.py +0 -59
  250. {tomwer/test → orangecontrib/tomwer/tutorials}/__init__.py +0 -0
  251. /tomwer/{web/test → gui/control/serie}/__init__.py +0 -0
  252. /tomwer/{test → tests}/utils/__init__.py +0 -0
  253. /tomwer-1.0.4-py3.8-nspkg.pth → /tomwer-1.1.0-py3.9-nspkg.pth +0 -0
  254. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/LICENSE +0 -0
  255. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/namespace_packages.txt +0 -0
  256. {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/top_level.txt +0 -0
@@ -51,6 +51,7 @@ except ImportError:
51
51
  from silx.io.utils import h5py_read_dataset
52
52
  import logging
53
53
  from tomoscan.io import HDF5File
54
+ from typing import Optional
54
55
 
55
56
 
56
57
  _logger = logging.getLogger(__name__)
@@ -135,8 +136,19 @@ class BlissScan:
135
136
  return "@".join((str(entry), master_file))
136
137
 
137
138
  def _deduce_transfert_scan(self, output_dir):
138
- new_master_file = os.path.join(output_dir, os.path.basename(self.master_file))
139
- return BlissScan(master_file=new_master_file, entry=self.entry)
139
+ new_master_file = os.path.join(
140
+ output_dir,
141
+ os.path.basename(os.path.dirname(self.master_file)),
142
+ os.path.basename(self.master_file),
143
+ )
144
+ new_proposal_file = os.path.join(
145
+ output_dir, os.path.basename(self.proposal_file)
146
+ )
147
+ return BlissScan(
148
+ master_file=new_master_file,
149
+ proposal_file=new_proposal_file,
150
+ entry=self.entry,
151
+ )
140
152
 
141
153
  @staticmethod
142
154
  def is_bliss_file(file_path):
@@ -146,6 +158,29 @@ class BlissScan:
146
158
  # for now there is not real way to know if a scan is abort or not
147
159
  return False
148
160
 
161
+ def scan_dir_name(self) -> Optional[str]:
162
+ """for 'this/is/my/acquisition' returns 'acquisition'"""
163
+ if self.path is not None:
164
+ return self.path.split(os.sep)[-1]
165
+ else:
166
+ return None
167
+
168
+ def scan_basename(self) -> Optional[str]:
169
+ """for 'this/is/my/acquisition' returns 'acquisition'"""
170
+ if self.path is not None:
171
+ return self.path
172
+ else:
173
+ return None
174
+
175
+ def scan_parent_dir_basename(self) -> Optional[str]:
176
+ if self.path is not None:
177
+ try:
178
+ return os.path.dirname(self.path)
179
+ except Exception:
180
+ return None
181
+ else:
182
+ return None
183
+
149
184
  @staticmethod
150
185
  def is_bliss_valid_entry(file_path: str, entry: str):
151
186
  def is_pcotmo_tomo(current_title: str):
@@ -76,6 +76,10 @@ class EDFTomoScanIdentifier(_EDFTomoScanIdentifier, DatasetIdentifier):
76
76
  ObjClass=EDFTomoScan,
77
77
  )
78
78
 
79
+ def long_description(self) -> str:
80
+ """used for processview header tooltip for now"""
81
+ return self.to_str()
82
+
79
83
 
80
84
  class EDFTomoScan(_tsEDFTomoScan, TomwerScanBase):
81
85
  """
@@ -87,6 +91,8 @@ class EDFTomoScan(_tsEDFTomoScan, TomwerScanBase):
87
91
  def __init__(self, scan, overwrite_proc_file=False, update=True):
88
92
  _tsEDFTomoScan.__init__(self, scan=scan)
89
93
  TomwerScanBase.__init__(self)
94
+ # register at least the 'default' working directory as a possible reconstruction path
95
+ self.add_reconstruction_path(self.path)
90
96
 
91
97
  self._dark = None
92
98
  self._process_file = self.get_process_file_name(self)
@@ -99,19 +105,19 @@ class EDFTomoScan(_tsEDFTomoScan, TomwerScanBase):
99
105
  # fabio can raise some empty file error when data is not on disk (can be the case for the datawatcher when acquisiton is on going)
100
106
  pass
101
107
  try:
102
- reduced_darks = self.load_reduced_darks()
108
+ reduced_darks, metadata = self.load_reduced_darks(return_info=True)
103
109
  except (KeyError, OSError, ValueError):
104
110
  # file or key does not exists
105
111
  pass
106
112
  else:
107
- self.set_reduced_darks(reduced_darks)
113
+ self.set_reduced_darks(reduced_darks, darks_infos=metadata)
108
114
 
109
115
  try:
110
- reduced_flats = self.load_reduced_flats()
116
+ reduced_flats, metadata = self.load_reduced_flats(return_info=True)
111
117
  except (KeyError, OSError, ValueError):
112
118
  pass
113
119
  else:
114
- self.set_reduced_flats(reduced_flats)
120
+ self.set_reduced_flats(reduced_flats, flats_infos=metadata)
115
121
 
116
122
  @staticmethod
117
123
  def is_tomoscan_dir(
@@ -250,6 +256,10 @@ class EDFTomoScan(_tsEDFTomoScan, TomwerScanBase):
250
256
  indexStr = local_str.split("slice_pag_")[-1].split("_")[
251
257
  0
252
258
  ]
259
+ elif "slice_ctf_" in local_str:
260
+ indexStr = local_str.split("slice_ctf_")[-1].split("_")[
261
+ 0
262
+ ]
253
263
  else:
254
264
  indexStr = local_str.split("slice_")[-1].split("_")[0]
255
265
  if containsDigits(indexStr):
@@ -84,6 +84,10 @@ class HDF5TomoScanIdentifier(_HDF5TomoScanIdentifier, DatasetIdentifier):
84
84
  object=HDF5TomoScan, hdf5_file=hdf5_file, entry=entry
85
85
  )
86
86
 
87
+ def long_description(self) -> str:
88
+ """used for processview header tooltip for now"""
89
+ return self.to_str()
90
+
87
91
 
88
92
  class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
89
93
  """
@@ -105,25 +109,27 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
105
109
  def __init__(self, scan, entry, index=None, overwrite_proc_file=False):
106
110
  TomwerScanBase.__init__(self)
107
111
  _tsHDF5TomoScan.__init__(self, scan=scan, entry=entry, index=index)
112
+ # register at least the 'default' working directory as a possible reconstruction path
113
+ self.add_reconstruction_path(self.path)
108
114
 
109
115
  self._reconstruction_urls = None
110
116
  self._projections_with_angles = None
111
117
  self._process_file = self.get_process_file_name(self)
112
118
  self._init_index_process_file(overwrite_proc_file=overwrite_proc_file)
113
119
  try:
114
- reduced_darks = self.load_reduced_darks()
120
+ reduced_darks, metadata = self.load_reduced_darks(return_info=True)
115
121
  except (KeyError, OSError, ValueError):
116
122
  # file or key does not exists
117
123
  pass
118
124
  else:
119
- self.set_reduced_darks(reduced_darks)
125
+ self.set_reduced_darks(reduced_darks, darks_infos=metadata)
120
126
 
121
127
  try:
122
- reduced_flats = self.load_reduced_flats()
128
+ reduced_flats, metadata = self.load_reduced_flats(return_info=True)
123
129
  except (KeyError, OSError, ValueError):
124
130
  pass
125
131
  else:
126
- self.set_reduced_flats(reduced_flats)
132
+ self.set_reduced_flats(reduced_flats, flats_infos=metadata)
127
133
 
128
134
  @property
129
135
  def working_directory(self):
@@ -109,6 +109,7 @@ class TomwerScanBase(TomwerObject):
109
109
  "list of url related to latest slice reconstruction from nabu"
110
110
  self._latest_vol_reconstructions = []
111
111
  """list of url related to latest volume reconstruction from nabu"""
112
+ self._reconstruction_paths = set()
112
113
 
113
114
  def _clear_heavy_cache(self):
114
115
  """For scan for now we don't want to remove any information from the cache.
@@ -233,6 +234,13 @@ class TomwerScanBase(TomwerObject):
233
234
  def reconstructions(self, reconstructions):
234
235
  self._reconstructions = reconstructions
235
236
 
237
+ @property
238
+ def reconstruction_paths(self):
239
+ return self._reconstruction_paths
240
+
241
+ def add_reconstruction_path(self, path: str):
242
+ self._reconstruction_paths.add(path)
243
+
236
244
  @property
237
245
  def nabu_recons_params(self):
238
246
  return self._nabu_params
@@ -325,7 +333,7 @@ class TomwerScanBase(TomwerObject):
325
333
  from ..process.reconstruction.axis.anglemode import CorAngleMode
326
334
 
327
335
  _mode = CorAngleMode.from_value(mode)
328
- if self.path is None:
336
+ if self.path is None: # pylint: disable=E1101
329
337
  return None, None
330
338
 
331
339
  radios_with_angle = self.projections_with_angle()
@@ -461,10 +469,13 @@ class TomwerScanBase(TomwerObject):
461
469
  data = json.load(desc)
462
470
  else:
463
471
  data = desc
464
- if not (self.DICT_PATH_KEY in data and data[self.DICT_TYPE_KEY] == self._TYPE):
472
+ if not (
473
+ self.DICT_PATH_KEY in data # pylint: disable=E1101
474
+ and data[self.DICT_TYPE_KEY] == self._TYPE # pylint: disable=E1101
475
+ ):
465
476
  raise ValueError("Description is not an EDFScan json description")
466
477
 
467
- assert self.DICT_PATH_KEY in data
478
+ assert self.DICT_PATH_KEY in data # pylint: disable=E1101
468
479
  assert self._DICT_LAMINO_RP_KEY in data
469
480
  self.lamino_recons_params = data[self._DICT_LAMINO_RP_KEY]
470
481
  # load axis reconstruction parameters
@@ -516,10 +527,10 @@ class TomwerScanBase(TomwerObject):
516
527
  return (
517
528
  isinstance(other, self.__class__)
518
529
  or isinstance(self, other.__class__)
519
- and self.type == other.type
530
+ and self.type == other.type # pylint: disable=E1101
520
531
  and self.lamino_recons_params == other.lamino_recons_params
521
532
  and self.nabu_recons_params == other.nabu_recons_params
522
- and self.path == other.path
533
+ and self.path == other.path # pylint: disable=E1101
523
534
  )
524
535
 
525
536
  def get_sinogram(self, line, subsampling=1, norm_method=None, **kwargs):
@@ -599,23 +610,19 @@ class TomwerScanBase(TomwerObject):
599
610
  :return: list of urls that contains reconstruction from nabu
600
611
  :rtype: list
601
612
  """
602
- if (self.path is None) or (not os.path.isdir(self.path)):
613
+ all_recons_urls = set()
614
+ recons_paths = self.reconstruction_paths
615
+ for path in recons_paths:
616
+ all_recons_urls.update(self.get_reconstructions_urls_from_path(path))
617
+ return all_recons_urls
618
+
619
+ def get_reconstructions_urls_from_path(self, path, check_url=False):
620
+ if path is None or not os.path.isdir(path):
603
621
  return []
604
-
605
- results = []
606
-
607
- def get_recons_url_from_folder(folder, check_url=False):
608
- """
609
- retrieve all the url from a folder.
610
-
611
- :param str folder:
612
- :param bool check_url: if True before adding an url try to open it
613
- and insure is valid
614
- :return:
615
- """
622
+ else:
616
623
  res = set()
617
- for f in os.listdir(folder):
618
- current_path = os.path.join(folder, f)
624
+ for f in os.listdir(path):
625
+ current_path = os.path.join(path, f)
619
626
  if os.path.isfile(current_path):
620
627
  volume = _get_reconstructed_single_file_volume(
621
628
  current_path, scan=self
@@ -638,23 +645,20 @@ class TomwerScanBase(TomwerObject):
638
645
  pass
639
646
  else:
640
647
  res.update(
641
- get_recons_url_from_folder(
642
- folder=current_path, check_url=check_url
648
+ self.get_reconstructions_urls_from_path(
649
+ path=current_path, check_url=check_url
643
650
  )
644
651
  )
645
652
  return res
646
653
 
647
- results.extend(get_recons_url_from_folder(self.path))
648
- return results
649
-
650
654
  @property
651
655
  def latest_reconstructions(self):
652
- """List of latest reconstructions"""
656
+ """List of latest slices reconstructions (as VolumeIdentifier) - single slice volume"""
653
657
  return self._latest_reconstructions
654
658
 
655
659
  @property
656
660
  def latest_vol_reconstructions(self):
657
- """List of latest reconstructions"""
661
+ """List of latest volume reconstructions (as VolumeIdentifier)"""
658
662
  return self._latest_vol_reconstructions
659
663
 
660
664
  def clear_latest_reconstructions(self):
@@ -722,8 +726,10 @@ class TomwerScanBase(TomwerObject):
722
726
  res[value.path()] = key
723
727
  return res
724
728
 
725
- proj_inv_url_to_index = invert_dict(self.projections)
726
- alig_inv_url_to_index = invert_dict(self.alignment_projections)
729
+ proj_inv_url_to_index = invert_dict(self.projections) # pylint: disable=E1101
730
+ alig_inv_url_to_index = invert_dict(
731
+ self.alignment_projections # pylint: disable=E1101
732
+ )
727
733
  if url.path() in proj_inv_url_to_index:
728
734
  return proj_inv_url_to_index[url.path()]
729
735
  elif url.path() in alig_inv_url_to_index:
@@ -36,13 +36,11 @@ from tomoscan.identifier import BaseIdentifier, ScanIdentifier, VolumeIdentifier
36
36
  from tomoscan.tomoobject import TomoObject
37
37
  from tomwer.utils import docstring
38
38
  from typing import Union
39
- from .scanbase import TomwerScanBase
40
39
  from .edfscan import EDFTomoScan, EDFTomoScanIdentifier
41
40
  from .hdf5scan import HDF5TomoScan, HDF5TomoScanIdentifier
42
41
  from .blissscan import BlissScan
43
42
  import os
44
43
  import glob
45
- import json
46
44
  import logging
47
45
  from urllib.parse import urlparse
48
46
  from tomoscan.esrf.identifier.url_utils import split_path
@@ -114,6 +112,7 @@ class ScanFactory(object):
114
112
  else:
115
113
  raise ValueError(f"Scheme {scheme} not recognized")
116
114
 
115
+ @staticmethod
117
116
  def create_scan_object(scan_path, entry=None, accept_bliss_scan=False):
118
117
  """
119
118
 
@@ -130,7 +129,7 @@ class ScanFactory(object):
130
129
  raise ValueError("'scan_path' should be provided")
131
130
  if entry is not None and not entry.startswith("/"):
132
131
  entry = "/" + entry
133
- if ScanFactory.is_hdf5_tomo(scan_path):
132
+ if os.path.isfile(scan_path) and ScanFactory.is_hdf5_tomo(scan_path):
134
133
  valid_entries = _oHDF5TomoScan.get_valid_entries(scan_path)
135
134
  if entry is None:
136
135
  if len(valid_entries) > 1:
@@ -167,7 +166,7 @@ class ScanFactory(object):
167
166
  scan_path = scan_path.rstrip(os.path.sep)
168
167
  if EDFTomoScan.is_tomoscan_dir(scan_path):
169
168
  return (EDFTomoScan(scan=scan_path),)
170
- elif os.path.isfile(scan_path) and HDF5TomoScan.is_tomoscan_dir(scan_path):
169
+ elif HDF5TomoScan.is_tomoscan_dir(scan_path):
171
170
  scans = []
172
171
  master_file = HDF5TomoScan.get_master_file(scan_path=scan_path)
173
172
  entries = HDF5TomoScan.get_valid_entries(master_file)
@@ -254,16 +253,3 @@ class ScanFactory(object):
254
253
  return h5py.is_hdf5(scan_path)
255
254
  else:
256
255
  return HDF5TomoScan.directory_contains_scan(scan_path)
257
-
258
- @staticmethod
259
- def create_from_json(desc):
260
- """Create a ScanBase instance from a json description"""
261
- data = json.load(desc)
262
-
263
- if TomwerScanBase._DICT_TYPE_KEY not in data:
264
- raise ValueError("json not recognize")
265
- elif data[TomwerScanBase._DICT_TYPE_KEY] == EDFTomoScan._TYPE:
266
- scan = EDFTomoScan(scan=None).load_from_dict(data)
267
- return scan
268
- else:
269
- raise ValueError("Type", data[TomwerScanBase.type], "is not managed")
@@ -32,7 +32,7 @@ import unittest
32
32
  import shutil
33
33
  import os
34
34
  import tempfile
35
- from tomwer.test.utils import UtilsTest
35
+ from tomwer.tests.utils import UtilsTest
36
36
  from tomwer.core.scan.hdf5scan import HDF5TomoScan
37
37
  from tomwer.core.process.reconstruction.darkref.darkrefs import DarkRefs
38
38
  from tomwer.core.utils.scanutils import MockHDF5
@@ -141,14 +141,3 @@ class TestProcessRegistration(unittest.TestCase):
141
141
  self.assertEqual(nodes["/entry/tomwer_process_16"], 16)
142
142
  self.assertTrue("/entry/tomwer_process_1" in nodes)
143
143
  self.assertEqual(nodes["/entry/tomwer_process_1"], 1)
144
-
145
-
146
- def suite():
147
- test_suite = unittest.TestSuite()
148
- for ui in (TestProcessRegistration,):
149
- test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ui))
150
- return test_suite
151
-
152
-
153
- if __name__ == "__main__":
154
- unittest.main(defaultTest="suite")
@@ -36,7 +36,7 @@ import contextlib
36
36
  from tomwer.core.scan.edfscan import EDFTomoScan
37
37
  from tomwer.core.scan.scanfactory import ScanFactory
38
38
  from tomwer.core.process.task import Task
39
- from tomwer.test.utils import UtilsTest
39
+ from tomwer.tests.utils import UtilsTest
40
40
  from tomwer.core.utils.scanutils import MockEDF
41
41
  from tomwer.core.process.reconstruction.nabu import nabuslices
42
42
  import shutil
@@ -90,38 +90,40 @@ class TestScanValidatorFindNabuFiles(unittest.TestCase):
90
90
 
91
91
  def test(self) -> None:
92
92
  for slice_index in (None, 1, 15):
93
- for pag_db in (None, 100, 500):
94
- file_name = (
95
- nabuslices.SingleSliceRunner.get_file_basename_reconstruction(
96
- slice_index=slice_index,
97
- scan=self.scan,
98
- pag=pag_db is not None,
99
- db=pag_db,
100
- )
101
- )
102
- for file_extension in ("npy", "npz", "hdf5"):
103
- with self.subTest(
104
- slice_index=slice_index,
105
- pag_db=pag_db,
106
- file_extension=file_extension,
107
- ):
108
- file_path = os.path.join(
109
- self.scan.path, file_name + "." + file_extension
93
+ for delta_beta in (None, 100, 500):
94
+ for pag in (True, False):
95
+ for ctf in (True, False):
96
+ file_name = nabuslices.SingleSliceRunner.get_file_basename_reconstruction(
97
+ slice_index=slice_index,
98
+ scan=self.scan,
99
+ pag=pag if delta_beta is not None else False,
100
+ ctf=ctf if delta_beta is not None else False,
101
+ db=delta_beta,
110
102
  )
111
-
112
- # simple context Manager which create the file
113
- # and remove it when leave
114
- with TestScanValidatorFindNabuFiles.FileCreator(file_path):
115
- n_to_discover = 1
116
- if slice_index is None:
117
- n_to_discover = 0
118
- self.assertEqual(
119
- len(
120
- self.scan.get_reconstructions_paths(self.scan.path)
121
- ),
122
- n_to_discover,
103
+ print("file_name is", file_name)
104
+ with self.subTest(
105
+ slice_index=slice_index,
106
+ pag_db=delta_beta,
107
+ ):
108
+ file_path = os.path.join(
109
+ self.scan.path, file_name + ".hdf5"
123
110
  )
124
111
 
112
+ # simple context Manager which create the file
113
+ # and remove it when leave
114
+ with TestScanValidatorFindNabuFiles.FileCreator(file_path):
115
+ n_to_discover = 1
116
+ if slice_index is None:
117
+ n_to_discover = 0
118
+ self.assertEqual(
119
+ len(
120
+ self.scan.get_reconstructions_paths(
121
+ self.scan.path
122
+ )
123
+ ),
124
+ n_to_discover,
125
+ )
126
+
125
127
 
126
128
  class TestScanValidatorFindPyHSTFiles(unittest.TestCase):
127
129
  """Function testing the getReconstructionsPaths function is correctly
tomwer/core/settings.py CHANGED
@@ -96,7 +96,7 @@ class SlurmSettings:
96
96
  MEMORY_PER_WORKER = 50 # memory in GB
97
97
  """Amount of memory per worker"""
98
98
 
99
- PARTIION = "p9gpu"
99
+ PARTITION = "p9gpu"
100
100
  """Queue / partition to use"""
101
101
 
102
102
  DEFAULT_WALLTIME = "01:00:00" # None if the default wall time
@@ -104,7 +104,7 @@ class SlurmSettings:
104
104
  N_GPUS_PER_WORKER = 1
105
105
  """number of gpu per worker"""
106
106
 
107
- PYTHON_VENV = "/scisoft/tomotools_env/tomwer/activate.sh latest"
107
+ PYTHON_VENV = "/scisoft/tomotools/activate.sh stable"
108
108
  """Python executable to take. Useful if compute nodes have a different environment from the front end.
109
109
  """
110
110
 
@@ -34,7 +34,7 @@ import os
34
34
  import shutil
35
35
  from tomwer.core import utils
36
36
  from tomwer.core.utils.scanutils import MockEDF, MockHDF5
37
- from tomwer.test.utils import UtilsTest
37
+ from tomwer.tests.utils import UtilsTest
38
38
  from tomwer.core.utils.normalization import flatFieldCorrection
39
39
  import numpy
40
40
 
@@ -6,6 +6,7 @@ class TomwerObject(Dataset):
6
6
 
7
7
  def __init__(self) -> None:
8
8
  super().__init__()
9
+ self._cast_volume = None
9
10
 
10
11
  def _clear_heavy_cache(self):
11
12
  """util function to clear some heavy object from the cache"""
@@ -13,3 +14,21 @@ class TomwerObject(Dataset):
13
14
 
14
15
  def clear_caches(self):
15
16
  pass
17
+
18
+ @property
19
+ def cast_volume(self):
20
+ # for now this is used as an east way to cache the identifier and provide it to the remaining of the orange canvas.
21
+ # but this is a wrong designa and should be removed at one point.
22
+ return self._cast_volume
23
+
24
+ @cast_volume.setter
25
+ def cast_volume(self, volume):
26
+ from tomwer.core.volume.volumebase import TomwerVolumeBase
27
+
28
+ if not isinstance(volume, TomwerVolumeBase):
29
+ from tomwer.core.volume.volumefactory import (
30
+ VolumeFactory,
31
+ ) # avoid cyclic import
32
+
33
+ volume = VolumeFactory.create_tomo_object_from_identifier(identifier=volume)
34
+ self._cast_volume = volume
@@ -338,50 +338,6 @@ def getDim1Dim2(scan):
338
338
  return d1, d2
339
339
 
340
340
 
341
- # TODO: move to scan module
342
- def getStartEndVoxels(scan):
343
- _info_file = os.path.join(scan, os.path.basename(scan) + ".info")
344
- sv_1 = _getInformation(
345
- scan=scan,
346
- refFile=_info_file,
347
- information="START_VOXEL_1",
348
- aliases=["projectionSize/ROW_BEG"],
349
- )
350
- ev_1 = _getInformation(
351
- scan=scan,
352
- refFile=_info_file,
353
- information="END_VOXEL_1",
354
- aliases=["projectionSize/ROW_END"],
355
- )
356
-
357
- sv_2 = _getInformation(
358
- scan=scan,
359
- refFile=_info_file,
360
- information="START_VOXEL_2",
361
- aliases=["projectionSize/COL_BEG"],
362
- )
363
- ev_2 = _getInformation(
364
- scan=scan,
365
- refFile=_info_file,
366
- information="END_VOXEL_2",
367
- aliases=["projectionSize/COL_END"],
368
- )
369
-
370
- sv_3 = _getInformation(scan=scan, refFile=_info_file, information="START_VOXEL_3")
371
- ev_3 = _getInformation(scan=scan, refFile=_info_file, information="END_VOXEL_3")
372
-
373
- dim_1, dim_2 = getDim1Dim2(scan=scan)
374
- sv_1 = sv_1 or 0
375
- sv_2 = sv_2 or 0
376
- sv_3 = sv_3 or 0
377
-
378
- ev_1 = ev_1 or dim_1 - 1
379
- ev_2 = ev_2 or dim_1 - 1
380
- ev_3 = ev_3 or dim_2 - 1
381
-
382
- return (sv_1, ev_1, sv_2, ev_2, sv_3, ev_3)
383
-
384
-
385
341
  # TODO: move to scan module
386
342
  def getParametersFromParOrInfo(_file):
387
343
  """
@@ -461,7 +417,6 @@ def getPixelSize(scan):
461
417
 
462
418
 
463
419
  url_base = "http://www.edna-site.org/pub/tomwer/"
464
- # url_base = 'http://ftp.edna-site.org/tomwer/'
465
420
 
466
421
 
467
422
  def DownloadDataset(dataset, output_folder, timeout, unpack=False):
tomwer/core/utils/char.py CHANGED
@@ -39,3 +39,5 @@ DELTA_CHAR = (b"\xce\xb4").decode("utf-8")
39
39
  PSI_CHAR = (b"\xcf\x88").decode("utf-8")
40
40
 
41
41
  THETA_CHAR = (b"\xce\xb8").decode("utf-8")
42
+
43
+ MU_CHAR = (b"\xce\xbc").decode("utf-8")
tomwer/core/utils/gpu.py CHANGED
@@ -35,12 +35,12 @@ _logger = logging.getLogger(__name__)
35
35
 
36
36
  def getNumberOfDevice():
37
37
  try:
38
- import pycuda # noqa F401
39
- from pycuda import compiler # noqa F401
40
- import pycuda.driver as drv
38
+ import pycuda # noqa F401 pylint: disable=E0401
39
+ from pycuda import compiler # noqa F401 pylint: disable=E0401
40
+ from pycuda import driver # pylint: disable=E0401
41
41
 
42
- drv.init()
43
- return drv.Device.count()
42
+ driver.init()
43
+ return driver.Device.count()
44
44
  except Exception:
45
45
  _logger.error("fail to discover the number of gpu")
46
46
  return None
@@ -29,7 +29,7 @@ __date__ = "02/12/2021"
29
29
 
30
30
 
31
31
  from typing import Union
32
- from tomoscan.esrf.hdf5scan import ImageKey
32
+ from tomoscan.esrf.scan.hdf5scan import ImageKey
33
33
  import numpy
34
34
 
35
35
 
@@ -38,7 +38,7 @@ def get_n_series(image_key_values: Union[tuple, list], image_key_type: ImageKey)
38
38
  Return the number of series of an inage_key. Image key can be dark, flat, or projection.
39
39
  A serie is defined as a contiguous elements in image_key_values
40
40
 
41
- :param image_key_values: list or tuple of image_keys to consider. Can be integers or tomoscan.esrf.hdf5scan.ImageKey
41
+ :param image_key_values: list or tuple of image_keys to consider. Can be integers or tomoscan.esrf.scan.hdf5scan.ImageKey
42
42
  """
43
43
  image_key_type = ImageKey.from_value(image_key_type)
44
44
  if image_key_type is ImageKey.INVALID: