tomwer 1.0.3__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 (269) 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 +3 -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 -129
  20. orangecontrib/tomwer/widgets/control/NotifierOW.py +34 -9
  21. orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +3 -5
  22. orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +19 -13
  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 +73 -78
  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 -11
  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 -20
  47. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +24 -18
  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/intensitynormalization.py +0 -1
  66. tomwer/app/nxtomoeditor.py +103 -0
  67. tomwer/app/rsync.py +1 -1
  68. tomwer/core/cluster/cluster.py +1 -1
  69. tomwer/core/futureobject.py +1 -0
  70. tomwer/core/process/control/datalistener/datalistener.py +7 -1
  71. tomwer/core/process/control/datalistener/rpcserver.py +3 -4
  72. tomwer/core/process/control/datawatcher/datawatcher.py +18 -18
  73. tomwer/core/process/control/datawatcher/datawatcherobserver.py +5 -8
  74. tomwer/core/process/control/datawatcher/datawatcherprocess.py +2 -3
  75. tomwer/core/process/control/datawatcher/edfdwprocess.py +2 -2
  76. tomwer/core/process/control/nxtomomill.py +33 -58
  77. tomwer/core/process/control/scanlist.py +2 -1
  78. tomwer/core/process/control/scanselector.py +7 -0
  79. tomwer/core/process/control/scantransfer.py +2 -2
  80. tomwer/core/process/control/scanvalidator.py +6 -5
  81. tomwer/core/process/control/singletomoobj.py +2 -1
  82. tomwer/core/process/control/timer.py +2 -1
  83. tomwer/core/process/control/tomoobjserie.py +8 -2
  84. tomwer/core/process/control/volumeselector.py +2 -1
  85. tomwer/core/process/control/volumesymlink.py +2 -1
  86. tomwer/core/process/edit/darkflatpatch.py +2 -1
  87. tomwer/core/process/edit/imagekeyeditor.py +4 -3
  88. tomwer/core/process/reconstruction/axis/axis.py +29 -32
  89. tomwer/core/process/reconstruction/axis/mode.py +3 -2
  90. tomwer/core/process/reconstruction/axis/params.py +35 -16
  91. tomwer/core/process/reconstruction/darkref/darkrefs.py +90 -707
  92. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +44 -16
  93. tomwer/core/process/reconstruction/darkref/params.py +62 -67
  94. tomwer/core/process/reconstruction/lamino/tofu.py +1 -2
  95. tomwer/core/process/reconstruction/nabu/castvolume.py +21 -26
  96. tomwer/core/process/reconstruction/nabu/nabucommon.py +36 -38
  97. tomwer/core/process/reconstruction/nabu/nabuscores.py +28 -13
  98. tomwer/core/process/reconstruction/nabu/nabuslices.py +41 -14
  99. tomwer/core/process/reconstruction/nabu/nabuvolume.py +21 -12
  100. tomwer/core/process/reconstruction/nabu/utils.py +32 -3
  101. tomwer/core/process/reconstruction/normalization/normalization.py +9 -8
  102. tomwer/core/process/reconstruction/saaxis/saaxis.py +46 -20
  103. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +38 -12
  104. tomwer/core/process/reconstruction/test/__init__.py +0 -39
  105. tomwer/core/process/reconstruction/test/test_axis_params.py +25 -3
  106. tomwer/core/process/reconstruction/test/test_darkref_copy.py +117 -1
  107. tomwer/core/process/script/python.py +16 -12
  108. tomwer/core/process/task.py +3 -7
  109. tomwer/core/process/test/test_axis.py +1 -1
  110. tomwer/core/process/test/test_dark_and_flat.py +41 -111
  111. tomwer/core/process/test/test_data_listener.py +0 -29
  112. tomwer/core/process/test/test_data_transfer.py +10 -14
  113. tomwer/core/process/test/test_nabu.py +1 -1
  114. tomwer/core/process/test/test_normalization.py +1 -1
  115. tomwer/core/process/visualization/liveslice.py +6 -0
  116. tomwer/core/scan/blissscan.py +37 -2
  117. tomwer/core/scan/edfscan.py +19 -8
  118. tomwer/core/scan/hdf5scan.py +10 -4
  119. tomwer/core/scan/scanbase.py +35 -29
  120. tomwer/core/scan/scanfactory.py +3 -17
  121. tomwer/core/scan/test/test_h5.py +1 -1
  122. tomwer/core/scan/test/test_process_registration.py +0 -11
  123. tomwer/core/scan/test/test_scan.py +32 -30
  124. tomwer/core/settings.py +2 -2
  125. tomwer/core/test/test_utils.py +1 -1
  126. tomwer/core/tomwer_object.py +19 -0
  127. tomwer/core/utils/__init__.py +0 -45
  128. tomwer/core/utils/char.py +2 -0
  129. tomwer/core/utils/gpu.py +5 -5
  130. tomwer/core/utils/nxtomoutils.py +2 -2
  131. tomwer/core/utils/scanutils.py +50 -0
  132. tomwer/core/utils/volumeutils.py +13 -0
  133. tomwer/core/volume/edfvolume.py +4 -0
  134. tomwer/core/volume/hdf5volume.py +4 -0
  135. tomwer/core/volume/jp2kvolume.py +4 -0
  136. tomwer/core/volume/rawvolume.py +22 -5
  137. tomwer/core/volume/tiffvolume.py +4 -0
  138. tomwer/core/volume/volumebase.py +19 -12
  139. tomwer/core/volume/volumefactory.py +20 -1
  140. tomwer/gui/cluster/slurm.py +1 -1
  141. tomwer/gui/cluster/supervisor.py +0 -2
  142. tomwer/gui/cluster/test/test_cluster.py +2 -2
  143. tomwer/gui/control/datalist.py +109 -36
  144. tomwer/gui/control/datatransfert.py +1 -1
  145. tomwer/gui/control/datawatcher/configuration.py +0 -2
  146. tomwer/gui/control/datawatcher/datawatcher.py +23 -13
  147. tomwer/gui/control/datawatcher/datawatcherobserver.py +1 -1
  148. tomwer/gui/control/observations.py +0 -3
  149. tomwer/gui/control/selectorwidgetbase.py +42 -12
  150. tomwer/gui/control/serie/seriecreator.py +967 -0
  151. tomwer/{web/__init__.py → gui/control/serie/seriewaiter.py} +5 -7
  152. tomwer/gui/control/singletomoobj.py +15 -4
  153. tomwer/gui/control/test/test_datalist.py +1 -1
  154. tomwer/gui/control/test/test_datalistener.py +1 -1
  155. tomwer/gui/control/test/test_inputwidget.py +1 -1
  156. tomwer/gui/control/test/test_process_manager.py +1 -13
  157. tomwer/gui/control/test/test_scanselector.py +1 -1
  158. tomwer/gui/control/test/test_scanvalidator.py +1 -1
  159. tomwer/gui/control/test/test_single_tomo_obj.py +1 -1
  160. tomwer/gui/control/test/test_volume_dialog.py +19 -7
  161. tomwer/gui/control/test/test_volumeselector.py +4 -4
  162. tomwer/gui/debugtools/datasetgenerator.py +1 -9
  163. tomwer/gui/edit/dkrfpatch.py +2 -3
  164. tomwer/gui/edit/imagekeyeditor.py +12 -11
  165. tomwer/gui/edit/nxtomoeditor.py +475 -0
  166. tomwer/gui/edit/test/test_dkrf_patch.py +2 -14
  167. tomwer/gui/edit/test/test_image_key_editor.py +2 -2
  168. tomwer/gui/edit/test/test_nx_editor.py +155 -0
  169. tomwer/gui/icons.py +0 -1
  170. tomwer/gui/qfolderdialog.py +11 -0
  171. tomwer/gui/reconstruction/axis/CompareImages.py +27 -29
  172. tomwer/gui/reconstruction/axis/axis.py +2 -0
  173. tomwer/gui/reconstruction/axis/radioaxis.py +70 -14
  174. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +7 -9
  175. tomwer/gui/reconstruction/darkref/darkrefwidget.py +22 -24
  176. tomwer/gui/reconstruction/lamino/tofu/projections.py +1 -1
  177. tomwer/gui/reconstruction/lamino/tofu/tofu.py +3 -3
  178. tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +4 -4
  179. tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +10 -5
  180. tomwer/gui/reconstruction/nabu/castvolume.py +103 -24
  181. tomwer/gui/reconstruction/nabu/check.py +1 -1
  182. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +352 -0
  183. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +0 -9
  184. tomwer/gui/reconstruction/nabu/nabuconfig/output.py +1 -1
  185. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +18 -19
  186. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +30 -7
  187. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +26 -15
  188. tomwer/gui/reconstruction/nabu/slices.py +10 -4
  189. tomwer/gui/reconstruction/nabu/slurm.py +1 -1
  190. tomwer/gui/reconstruction/nabu/volume.py +13 -7
  191. tomwer/gui/reconstruction/normalization/intensity.py +1 -5
  192. tomwer/gui/reconstruction/saaxis/corrangeselector.py +10 -37
  193. tomwer/gui/reconstruction/saaxis/saaxis.py +11 -7
  194. tomwer/gui/reconstruction/saaxis/sliceselector.py +11 -26
  195. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +13 -8
  196. tomwer/gui/reconstruction/scores/scoreplot.py +67 -62
  197. tomwer/gui/reconstruction/test/test_axis.py +2 -2
  198. tomwer/gui/reconstruction/test/test_lamino.py +2 -2
  199. tomwer/gui/reconstruction/test/test_nabu.py +14 -1
  200. tomwer/gui/reconstruction/test/test_saaxis.py +8 -17
  201. tomwer/gui/reconstruction/test/test_sadeltabeta.py +7 -13
  202. tomwer/gui/stackplot.py +11 -28
  203. tomwer/gui/test/test_axis_gui.py +4 -4
  204. tomwer/gui/test/test_qfolder_dialog.py +12 -0
  205. tomwer/gui/utils/inputwidget.py +42 -22
  206. tomwer/gui/utils/lineselector/lineselector.py +13 -21
  207. tomwer/gui/utils/scandescription.py +2 -4
  208. tomwer/gui/utils/slider.py +1 -102
  209. tomwer/gui/utils/unitsystem.py +48 -11
  210. tomwer/gui/visualization/dataviewer.py +24 -17
  211. tomwer/gui/visualization/diffviewer/diffviewer.py +2 -11
  212. tomwer/gui/visualization/nxtomometadata.py +21 -0
  213. tomwer/gui/visualization/scanoverview.py +0 -1
  214. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +72 -0
  215. tomwer/gui/visualization/test/test_stacks.py +1 -1
  216. tomwer/gui/visualization/tomoobjoverview.py +49 -0
  217. tomwer/gui/visualization/volumeoverview.py +64 -0
  218. tomwer/gui/visualization/volumeviewer.py +1 -1
  219. tomwer/io/utils/utils.py +2 -2
  220. tomwer/resources/gui/icons/multi-document-save.png +0 -0
  221. tomwer/resources/gui/icons/multi-document-save.svg +101 -0
  222. tomwer/resources/gui/illustrations/ctf_z1.png +0 -0
  223. tomwer/resources/gui/illustrations/ctf_z1.svg +471 -0
  224. tomwer/synctools/axis.py +0 -1
  225. tomwer/synctools/darkref.py +0 -1
  226. tomwer/synctools/datalistener.py +5 -1
  227. tomwer/synctools/imageloaderthread.py +2 -2
  228. tomwer/synctools/saaxis.py +0 -1
  229. tomwer/synctools/sadeltabeta.py +0 -1
  230. tomwer/synctools/stacks/edit/imagekeyeditor.py +1 -1
  231. tomwer/synctools/stacks/processingstack.py +2 -2
  232. tomwer/synctools/stacks/reconstruction/castvolume.py +1 -0
  233. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +1 -1
  234. tomwer/synctools/stacks/reconstruction/lamino.py +1 -3
  235. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +0 -2
  236. tomwer/synctools/test/test_darkRefs.py +32 -149
  237. tomwer/synctools/test/test_foldertransfer.py +1 -1
  238. tomwer/synctools/test/test_scanstages.py +2 -2
  239. tomwer/tests/conftest.py +51 -0
  240. tomwer/{test → tests}/test_scripts.py +1 -1
  241. tomwer/tests/test_utils.py +10 -0
  242. tomwer/{test → tests}/utils/utilstest.py +0 -11
  243. tomwer/version.py +3 -3
  244. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/METADATA +14 -16
  245. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/RECORD +255 -235
  246. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/WHEEL +1 -1
  247. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/entry_points.txt +6 -0
  248. orangecontrib/tomwer/setup.py +0 -45
  249. orangecontrib/tomwer/widgets/setup.py +0 -49
  250. tomwer/app/process.py +0 -153
  251. tomwer/core/process/reconstruction/nabu/slurm.py +0 -36
  252. tomwer/core/process/reconstruction/utils/nabu_slice_exec.py +0 -10
  253. tomwer/core/utils/laminoutils.py +0 -80
  254. tomwer/gui/utils/lineselector/lineselection.py +0 -76
  255. tomwer/setup.py +0 -52
  256. tomwer/slurm/executor.py +0 -36
  257. tomwer/slurm/job.py +0 -349
  258. tomwer/slurm/utils.py +0 -44
  259. tomwer/web/client.py +0 -43
  260. tomwer/web/config.py +0 -36
  261. tomwer/web/test/test_graylog_connection.py +0 -59
  262. {tomwer/slurm → orangecontrib/tomwer/tutorials}/__init__.py +0 -0
  263. /tomwer/{test → gui/control/serie}/__init__.py +0 -0
  264. /tomwer/{web/test → tests}/__init__.py +0 -0
  265. /tomwer/{test → tests}/utils/__init__.py +0 -0
  266. /tomwer-1.0.3-py3.8-nspkg.pth → /tomwer-1.1.0-py3.9-nspkg.pth +0 -0
  267. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/LICENSE +0 -0
  268. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/namespace_packages.txt +0 -0
  269. {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/top_level.txt +0 -0
tomwer/slurm/job.py DELETED
@@ -1,349 +0,0 @@
1
- from pathlib import Path
2
- import shutil
3
- import tempfile
4
- from typing import Optional
5
- import os
6
- from tomwer.slurm.utils import SubProcessCommand
7
- from .utils import has_scancel_available, has_scontrol_available
8
- import time
9
- import logging
10
-
11
- _logger = logging.getLogger(__name__)
12
-
13
-
14
- class Job:
15
- def __init__(self, working_directory) -> None:
16
- """
17
- :param script: script to be launched
18
- """
19
- self._working_directory = working_directory
20
- self._dry_run = False
21
- self._result = "not run yet"
22
-
23
- @property
24
- def working_directory(self) -> Optional[str]:
25
- return self._working_directory
26
-
27
- @property
28
- def result(self):
29
- return self._result
30
-
31
- @property
32
- def dry_run(self):
33
- return self._dry_run
34
-
35
- @dry_run.setter
36
- def dry_run(self, dry_run: bool):
37
- self._dry_run = dry_run
38
-
39
- def run(self):
40
- raise NotImplementedError("Base class")
41
-
42
-
43
- class ScriptJob(Job):
44
- def __init__(
45
- self,
46
- script: tuple,
47
- working_directory: Optional[Path] = None,
48
- script_path: Optional[Path] = None,
49
- clean_script: bool = True,
50
- clean_job_artefacts: bool = True,
51
- ) -> None:
52
- """
53
- :param tuple script: script with a tuple of str (one per line to write)
54
- """
55
- if not isinstance(script, tuple):
56
- raise TypeError(
57
- f"script is expected to be a tuple. {type(script)} provided"
58
- )
59
- super().__init__(working_directory)
60
- self._clean_script = clean_script
61
- self._script_path = script_path
62
- self._script = list(script)
63
- self._overwrite = False
64
- self._file_extension = "sh"
65
- self._clean_job_artefacts = clean_job_artefacts
66
-
67
- @property
68
- def script(self) -> tuple:
69
- return tuple(self._script)
70
-
71
- @property
72
- def file_extension(self):
73
- return self._file_extension
74
-
75
- @file_extension.setter
76
- def file_extension(self, file_extension: str):
77
- self._file_extension = file_extension.lsplit(".")
78
-
79
- @property
80
- def overwrite(self) -> bool:
81
- return self._overwrite
82
-
83
- @overwrite.setter
84
- def overwrite(self, overwrite: bool):
85
- self._overwrite = overwrite
86
-
87
- @property
88
- def script_path(self) -> Optional[Path]:
89
- return self._script_path
90
-
91
- @property
92
- def clean_script(self):
93
- return self._clean_script
94
-
95
- @clean_script.setter
96
- def clean_script(self, clean_script: bool):
97
- self._clean_script = clean_script
98
-
99
- @property
100
- def clean_job_artefacts(self) -> bool:
101
- return self._clean_job_artefacts
102
-
103
- @clean_job_artefacts.setter
104
- def clean_job_artefacts(self, clean: bool):
105
- return self._clean_job_artefacts
106
-
107
- def _save_script(self) -> Path:
108
- if self.script_path is not None:
109
- if os.path.exists(self.script_path) and not os.path.isfile(
110
- self.script_path
111
- ):
112
- raise ValueError(
113
- f"script_path is expected to be a file path ({self.script_path})"
114
- )
115
- else:
116
- self._script_path = ".".join(
117
- [tempfile.NamedTemporaryFile().name, self.file_extension]
118
- )
119
- os.makedirs(os.path.dirname(self.script_path), exist_ok=True)
120
- # warning: for compatiblity with batchScript the file should always be set to self._script_path
121
- # before calling _write_script_preprocessing_lines
122
- mode = "w" if self.overwrite else "x"
123
- with open(self.script_path, mode=mode) as file_object:
124
- self._specify_shell_command(file_object)
125
- self._write_script_preprocessing_lines(file_object)
126
- self._write_script_lines(file_object)
127
- self._write_script_postprocessing_lines(file_object)
128
- return self.script_path
129
-
130
- def _specify_shell_command(self, file_object):
131
- file_object.write("#!/bin/bash\n")
132
-
133
- def _write_script_lines(self, file_object):
134
- for line in self.script:
135
- file_object.write(line + "\n")
136
-
137
- def _write_script_preprocessing_lines(self, file_object):
138
- if self._working_directory is not None:
139
- file_object.write(f"#SBATCH --chdir={self.working_directory}\n")
140
-
141
- def _write_script_postprocessing_lines(self, file_object):
142
- pass
143
-
144
- def _do_script_cleaning(self):
145
- if self.script_path is not None and os.path.isfile(self.script_path):
146
- os.remove(self.script_path)
147
-
148
- def _do_job_artefacts_cleaning(self):
149
- pass
150
-
151
-
152
- class SBatchScriptJob(ScriptJob):
153
- def __init__(self, slurm_config: Optional[dict] = None, *args, **kwargs) -> None:
154
- super().__init__(*args, **kwargs)
155
- assert isinstance(slurm_config, (dict, type(None)))
156
- self._job_id = None
157
- self._status = "Under submission"
158
- self._slurm_config = slurm_config if slurm_config is not None else {}
159
-
160
- self._pycuda_cache_dir = os.path.join(
161
- os.path.dirname(self.script_path), ".pycuda_cache_dir"
162
- )
163
- # as we can have some incoherent home directory we need for some computer to define the pycuda cache directory (for iccbm181 for example)
164
- self._script.insert(0, f"mkdir -p {self._pycuda_cache_dir}")
165
- self._script.insert(1, f"export PYCUDA_CACHE_DIR={self._pycuda_cache_dir}")
166
-
167
- def set_status(self, status):
168
- self._status = status
169
-
170
- @property
171
- def job_id(self):
172
- return self._job_id
173
-
174
- @job_id.setter
175
- def job_id(self, job_id: int):
176
- self._job_id = job_id
177
-
178
- @property
179
- def status(self):
180
- return self._status
181
-
182
- def get_status(self):
183
- return self._status
184
-
185
- def run(self):
186
- self._status = "Running"
187
- script_path = self._save_script()
188
- if not os.path.exists(script_path):
189
- raise OSError(
190
- f"{script_path} doesn't exists. Unable to write script file. Can be write rights error."
191
- )
192
- if self.dry_run is False:
193
- job_id = SubProcessCommand(command=f"sbatch {script_path}").run()
194
- else:
195
- job_id = "-1"
196
- self._result = self._get_job_id_or_raise_error(job_id)
197
- if self.clean_script:
198
- self._do_script_cleaning()
199
- if self.clean_job_artefacts:
200
- self._do_job_artefacts_cleaning()
201
- return self._result
202
-
203
- def _get_job_id_or_raise_error(self, text: str) -> int:
204
- try:
205
- # we expect the slurm job ID to be the last element of the string
206
- return int(text.replace("\n", "").split(" ")[-1])
207
- except Exception as e:
208
- raise ValueError("Fail to get job id from submission") from e
209
-
210
- def _specify_shell_command(self, file_object):
211
- file_object.write("#!/bin/bash\n")
212
-
213
- def _write_script_preprocessing_lines(self, file_object):
214
- super()._write_script_preprocessing_lines(file_object=file_object)
215
- # handle first
216
- slurm_lines, pre_processing_lines = self.interpret_slurm_config(
217
- self._slurm_config
218
- )
219
- # define out file
220
- output_file_path = (
221
- str(self.script_path)[: -(len(self.file_extension) + 1)] + ".out"
222
- )
223
- file_object.write(f"#SBATCH --output={output_file_path}\n")
224
-
225
- for slurm_line in slurm_lines:
226
- file_object.write(slurm_line + "\n")
227
- for pre_processing_line in pre_processing_lines:
228
- file_object.write(pre_processing_line + "\n")
229
-
230
- def _do_job_artefacts_cleaning(self):
231
- if os.path.exists(self._pycuda_cache_dir):
232
- shutil.rmtree(self._pycuda_cache_dir, ignore_errors=True)
233
-
234
- @staticmethod
235
- def interpret_slurm_config(slurm_config: dict) -> tuple:
236
- """
237
- convert a slurm configuration dictory to a tuple of two tuples.
238
- The first tuple will provide the lines to add to the shell script for sbtach (ressources specification)
239
- The second line will provide some command to run before the 'processing command' like sourcing a python virtual environment
240
-
241
- :param dict slurm_config: slurm configuration to be interpreted
242
- :raise: KeyError if one the `slurm_config` dict cannot be interpreted
243
- """
244
- if not isinstance(slurm_config, dict):
245
- raise TypeError(
246
- f"slurm_config is expected to be a dict. {type(slurm_config)} provided"
247
- )
248
- slurm_ressources = []
249
- preprocessing = []
250
- for key, value in slurm_config.items():
251
- if value is None:
252
- continue
253
- if key == "cpu-per-task":
254
- slurm_ressources.append(f"#SBATCH --cpus-per-task={value}")
255
- elif key == "n_tasks":
256
- slurm_ressources.append(f"#SBATCH --ntasks={value}")
257
- elif key == "memory":
258
- slurm_ressources.append(f"#SBATCH --mem={value}GB")
259
- elif key == "partition":
260
- slurm_ressources.append(f"#SBATCH -p {value}")
261
- elif key == "n_gpus":
262
- slurm_ressources.append(f"#SBATCH --gres=gpu:{value}")
263
- elif key == "job_name":
264
- slurm_ressources.append(f"#SBATCH -J '{value}'")
265
- elif key == "walltime":
266
- slurm_ressources.append(f"#SBATCH -t {value}")
267
- elif key == "python_venv":
268
- preprocessing.append(f"source {value}")
269
- else:
270
- raise KeyError(f"Unknow slurm configuration key: {key}")
271
- return tuple(slurm_ressources), tuple(preprocessing)
272
-
273
-
274
- def get_job_status(job_id):
275
- if job_id is None:
276
- return "error"
277
- elif not has_scontrol_available():
278
- raise RuntimeError("squeue not available")
279
- else:
280
- res = SControlShowJobCommand(job_id=job_id).run()
281
- job_state = res.get("JobState", "FAILED")
282
- if job_state.lower() in (
283
- "out_of_memory",
284
- "suspended",
285
- "timeout",
286
- "nodefail",
287
- "preempted",
288
- "boot_fail",
289
- "deadline",
290
- " resv_del_hold",
291
- "revoked",
292
- ):
293
- _logger.warning(f"slurm job {job_id} failed with state {job_state}")
294
- job_state = "FAILED"
295
- return job_state.lower()
296
-
297
-
298
- def get_job_infos(job_id):
299
- if not has_scontrol_available():
300
- raise RuntimeError("squeue not available")
301
- else:
302
- return SControlShowJobCommand(job_id=job_id).run()
303
-
304
-
305
- def submit_sbatch_job(job):
306
- job_id = job.run()
307
- if not type(job_id) == int:
308
- return
309
- job.job_id = job_id
310
- while True:
311
- job_status = get_job_status(job_id)
312
- job.set_status(job_status)
313
- if job_status.lower() in ("completed", "failed", "cancelled", "finished"):
314
- infos = get_job_infos(job_id)
315
- job.infos = infos
316
- return job_status.lower()
317
- else:
318
- time.sleep(1)
319
-
320
-
321
- def cancel_slurm_job(job_id):
322
- if not has_scancel_available():
323
- raise RuntimeError("slurm command 'scancel' not available from this computer")
324
- else:
325
- return SubProcessCommand(command=f"scancel {job_id}").run()
326
-
327
-
328
- class SControlShowJobCommand(SubProcessCommand):
329
- def __init__(self, job_id, platform="Linux"):
330
- super().__init__(f"scontrol show job {job_id}", platform)
331
-
332
- def interpret_result(self, stdout, stderr):
333
- return self.stdout_to_dict(stdout=stdout)
334
-
335
- @staticmethod
336
- def stdout_to_dict(stdout):
337
- res = {}
338
- res_splitted = " ".join(stdout.split("\n"))
339
- res_splitted = res_splitted.split(" ")
340
- for elements in res_splitted:
341
- if elements == "":
342
- continue
343
- elements_splitted = elements.split("=", maxsplit=1)
344
- if len(elements_splitted) < 2:
345
- continue
346
-
347
- key, value = elements_splitted[0], elements_splitted[1]
348
- res[key] = value
349
- return res
tomwer/slurm/utils.py DELETED
@@ -1,44 +0,0 @@
1
- import subprocess
2
- import platform as _platform_mod
3
- from shutil import which
4
-
5
-
6
- def has_sbatch_available(platform="Linux"):
7
- return which("sbatch") is not None
8
-
9
-
10
- def has_scancel_available():
11
- return which("scancel") is not None
12
-
13
-
14
- def has_scontrol_available():
15
- return which("scontrol") is not None
16
-
17
-
18
- class SubProcessCommand:
19
- def __init__(self, command, platform="Linux"):
20
- if platform != _platform_mod.system():
21
- raise ValueError
22
- self._command = command
23
- self.raw_stdout = None
24
- self.raw_stderr = None
25
-
26
- def run(self):
27
- stdout, stderr = self.launch_command()
28
- self.raw_stdout = stdout.decode("utf-8")
29
- self.raw_stderr = stderr.decode("utf-8")
30
- return self.interpret_result(self.raw_stdout, self.raw_stderr)
31
-
32
- def interpret_result(self, stdout, stderr):
33
- return stdout
34
-
35
- def launch_command(self):
36
- process = subprocess.Popen(
37
- self._command,
38
- shell=True,
39
- stdout=subprocess.PIPE,
40
- stderr=subprocess.PIPE,
41
- )
42
- return process.communicate()
43
-
44
- __call__ = run
tomwer/web/client.py DELETED
@@ -1,43 +0,0 @@
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
- #############################################################################*/
24
- """module defining functions and class to communicate a status to the
25
- orange-server.
26
- The orange-server is used to display the advancement of the workflow.
27
- """
28
-
29
- __authors__ = ["H.Payno"]
30
- __license__ = "MIT"
31
- __date__ = "28/04/2017"
32
-
33
-
34
- import logging
35
-
36
- _logger = logging.getLogger(__name__)
37
-
38
-
39
- class OWClient(object):
40
- """Orange widget Client can emit information about his advancement"""
41
-
42
- WORKFLOW_INFO = "workflow" # general information about a workflow
43
- SCAN_INFO = "scan" # information focus on a scan
tomwer/web/config.py DELETED
@@ -1,36 +0,0 @@
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
- #############################################################################
24
- """module defining functions and class to communicate a status to the
25
- orange-server.
26
- The orange-server is used to display the advancement of the workflow.
27
- """
28
-
29
- __authors__ = ["H.Payno"]
30
- __license__ = "MIT"
31
- __date__ = "11/05/2017"
32
-
33
- grayport_port = 12204
34
- """Port of connection"""
35
- grayport_host = "graylog-dau"
36
- """host of connection"""
@@ -1,59 +0,0 @@
1
- # # coding: utf-8
2
- # # /*##########################################################################
3
- # #
4
- # # Copyright (c) 2016-2017 European Synchrotron Radiation Facility
5
- # #
6
- # # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # # of this software and associated documentation files (the "Software"), to deal
8
- # # in the Software without restriction, including without limitation the rights
9
- # # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # # copies of the Software, and to permit persons to whom the Software is
11
- # # furnished to do so, subject to the following conditions:
12
- # #
13
- # # The above copyright notice and this permission notice shall be included in
14
- # # all copies or substantial portions of the Software.
15
- # #
16
- # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- # # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- # # THE SOFTWARE.
23
- # #
24
- # # ###########################################################################*/
25
- # """ Not a unit test but send a simple test message error to gray log"""
26
- #
27
- # __authors__ = ["H. Payno"]
28
- # __license__ = "MIT"
29
- # __date__ = "24/01/2017"
30
- #
31
- # from tomwer.web.client import OWClient
32
- # import logging
33
- #
34
- # logger = logging.getLogger(__name__)
35
- #
36
- #
37
- # class TestGrayLog(OWClient):
38
- # def __init__(self):
39
- # OWClient.__init__(self)
40
- #
41
- # def sendErrorMessage(self):
42
- # logger.error("test error message")
43
- #
44
- # def sendwarningMessage(self):
45
- # logger.warning("test warning message")
46
- #
47
- # def sendInfoMessage(self):
48
- # logger.info("test info message")
49
- #
50
- # def sendProcessEndedMessage(self):
51
- # logger.processEnded("test processEnded message")
52
- #
53
- #
54
- # if __name__ == "__main__":
55
- # c = TestGrayLog()
56
- # c.sendErrorMessage()
57
- # c.sendwarningMessage()
58
- # c.sendInfoMessage()
59
- # c.sendProcessEndedMessage()
File without changes
File without changes
File without changes