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.
- orangecontrib/tomwer/tutorials/EBS_tomo_listener.ows +39 -0
- orangecontrib/tomwer/tutorials/cast_volume.ows +34 -0
- orangecontrib/tomwer/tutorials/simple_slice_reconstruction.ows +39 -0
- orangecontrib/tomwer/tutorials/simple_volume_local_reconstruction.ows +49 -0
- orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +59 -0
- orangecontrib/tomwer/tutorials/using_saaxis_to_find_cor.ows +44 -0
- orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +1 -1
- orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +14 -4
- orangecontrib/tomwer/widgets/cluster/__init__.py +1 -1
- orangecontrib/tomwer/widgets/control/DataListOW.py +12 -5
- orangecontrib/tomwer/widgets/control/DataListenerOW.py +18 -9
- orangecontrib/tomwer/widgets/control/DataSelectorOW.py +13 -6
- orangecontrib/tomwer/widgets/control/DataTransfertOW.py +3 -5
- orangecontrib/tomwer/widgets/control/DataValidatorOW.py +8 -4
- orangecontrib/tomwer/widgets/control/DataWatcherOW.py +4 -6
- orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +49 -62
- orangecontrib/tomwer/widgets/control/FilterOW.py +2 -4
- orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +93 -0
- orangecontrib/tomwer/widgets/control/NXTomomillOW.py +135 -129
- orangecontrib/tomwer/widgets/control/NotifierOW.py +34 -9
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +3 -5
- orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +19 -13
- orangecontrib/tomwer/widgets/control/VolumeSelector.py +12 -4
- orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +11 -7
- orangecontrib/tomwer/widgets/control/icons/notification.svg +4 -4
- orangecontrib/tomwer/widgets/control/icons/nxtomomill.png +0 -0
- orangecontrib/tomwer/widgets/control/icons/nxtomomill.svg +8 -5
- orangecontrib/tomwer/widgets/control/icons/tomoobjserie.png +0 -0
- orangecontrib/tomwer/widgets/control/icons/tomoobjserie.svg +73 -78
- orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +16 -4
- orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +100 -0
- orangecontrib/tomwer/widgets/edit/icons/image_key_editor.png +0 -0
- orangecontrib/tomwer/widgets/edit/icons/image_key_upgrader.png +0 -0
- orangecontrib/tomwer/widgets/edit/icons/nx_tomo_editor.png +0 -0
- orangecontrib/tomwer/widgets/edit/icons/nx_tomo_editor.svg +123 -0
- orangecontrib/tomwer/widgets/edit/test/test_dark_flat_patch.py +21 -1
- orangecontrib/tomwer/widgets/edit/test/test_image_key_editor.py +1 -1
- orangecontrib/tomwer/widgets/edit/test/test_image_key_upgrader.py +1 -1
- orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +25 -0
- orangecontrib/tomwer/widgets/other/PythonScriptOW.py +19 -11
- orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +20 -14
- orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +24 -10
- orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +26 -21
- orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +29 -12
- orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +44 -17
- orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +28 -20
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +24 -18
- orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +6 -6
- orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +4 -2
- orangecontrib/tomwer/widgets/reconstruction/icons/nabu_2d.png +0 -0
- orangecontrib/tomwer/widgets/reconstruction/icons/nabu_2d.svg +11 -8
- orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +10 -4
- orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +69 -0
- orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +2 -4
- orangecontrib/tomwer/widgets/visualization/icons/nx_tomo_metadata_viewer.png +0 -0
- orangecontrib/tomwer/widgets/visualization/icons/nx_tomo_metadata_viewer.svg +105 -0
- tomwer/__main__.py +10 -5
- tomwer/app/canvas_launcher/config.py +10 -10
- tomwer/app/canvas_launcher/mainwindow.py +68 -6
- tomwer/app/canvas_launcher/widgetsscheme.py +1 -3
- tomwer/app/darkref.py +16 -12
- tomwer/app/imagekeyeditor.py +2 -2
- tomwer/app/imagekeyupgrader.py +104 -0
- tomwer/app/intensitynormalization.py +0 -1
- tomwer/app/nxtomoeditor.py +103 -0
- tomwer/app/rsync.py +1 -1
- tomwer/core/cluster/cluster.py +1 -1
- tomwer/core/futureobject.py +1 -0
- tomwer/core/process/control/datalistener/datalistener.py +7 -1
- tomwer/core/process/control/datalistener/rpcserver.py +3 -4
- tomwer/core/process/control/datawatcher/datawatcher.py +18 -18
- tomwer/core/process/control/datawatcher/datawatcherobserver.py +5 -8
- tomwer/core/process/control/datawatcher/datawatcherprocess.py +2 -3
- tomwer/core/process/control/datawatcher/edfdwprocess.py +2 -2
- tomwer/core/process/control/nxtomomill.py +33 -58
- tomwer/core/process/control/scanlist.py +2 -1
- tomwer/core/process/control/scanselector.py +7 -0
- tomwer/core/process/control/scantransfer.py +2 -2
- tomwer/core/process/control/scanvalidator.py +6 -5
- tomwer/core/process/control/singletomoobj.py +2 -1
- tomwer/core/process/control/timer.py +2 -1
- tomwer/core/process/control/tomoobjserie.py +8 -2
- tomwer/core/process/control/volumeselector.py +2 -1
- tomwer/core/process/control/volumesymlink.py +2 -1
- tomwer/core/process/edit/darkflatpatch.py +2 -1
- tomwer/core/process/edit/imagekeyeditor.py +4 -3
- tomwer/core/process/reconstruction/axis/axis.py +29 -32
- tomwer/core/process/reconstruction/axis/mode.py +3 -2
- tomwer/core/process/reconstruction/axis/params.py +35 -16
- tomwer/core/process/reconstruction/darkref/darkrefs.py +90 -707
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +44 -16
- tomwer/core/process/reconstruction/darkref/params.py +62 -67
- tomwer/core/process/reconstruction/lamino/tofu.py +1 -2
- tomwer/core/process/reconstruction/nabu/castvolume.py +21 -26
- tomwer/core/process/reconstruction/nabu/nabucommon.py +36 -38
- tomwer/core/process/reconstruction/nabu/nabuscores.py +28 -13
- tomwer/core/process/reconstruction/nabu/nabuslices.py +41 -14
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +21 -12
- tomwer/core/process/reconstruction/nabu/utils.py +32 -3
- tomwer/core/process/reconstruction/normalization/normalization.py +9 -8
- tomwer/core/process/reconstruction/saaxis/saaxis.py +46 -20
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +38 -12
- tomwer/core/process/reconstruction/test/__init__.py +0 -39
- tomwer/core/process/reconstruction/test/test_axis_params.py +25 -3
- tomwer/core/process/reconstruction/test/test_darkref_copy.py +117 -1
- tomwer/core/process/script/python.py +16 -12
- tomwer/core/process/task.py +3 -7
- tomwer/core/process/test/test_axis.py +1 -1
- tomwer/core/process/test/test_dark_and_flat.py +41 -111
- tomwer/core/process/test/test_data_listener.py +0 -29
- tomwer/core/process/test/test_data_transfer.py +10 -14
- tomwer/core/process/test/test_nabu.py +1 -1
- tomwer/core/process/test/test_normalization.py +1 -1
- tomwer/core/process/visualization/liveslice.py +6 -0
- tomwer/core/scan/blissscan.py +37 -2
- tomwer/core/scan/edfscan.py +19 -8
- tomwer/core/scan/hdf5scan.py +10 -4
- tomwer/core/scan/scanbase.py +35 -29
- tomwer/core/scan/scanfactory.py +3 -17
- tomwer/core/scan/test/test_h5.py +1 -1
- tomwer/core/scan/test/test_process_registration.py +0 -11
- tomwer/core/scan/test/test_scan.py +32 -30
- tomwer/core/settings.py +2 -2
- tomwer/core/test/test_utils.py +1 -1
- tomwer/core/tomwer_object.py +19 -0
- tomwer/core/utils/__init__.py +0 -45
- tomwer/core/utils/char.py +2 -0
- tomwer/core/utils/gpu.py +5 -5
- tomwer/core/utils/nxtomoutils.py +2 -2
- tomwer/core/utils/scanutils.py +50 -0
- tomwer/core/utils/volumeutils.py +13 -0
- tomwer/core/volume/edfvolume.py +4 -0
- tomwer/core/volume/hdf5volume.py +4 -0
- tomwer/core/volume/jp2kvolume.py +4 -0
- tomwer/core/volume/rawvolume.py +22 -5
- tomwer/core/volume/tiffvolume.py +4 -0
- tomwer/core/volume/volumebase.py +19 -12
- tomwer/core/volume/volumefactory.py +20 -1
- tomwer/gui/cluster/slurm.py +1 -1
- tomwer/gui/cluster/supervisor.py +0 -2
- tomwer/gui/cluster/test/test_cluster.py +2 -2
- tomwer/gui/control/datalist.py +109 -36
- tomwer/gui/control/datatransfert.py +1 -1
- tomwer/gui/control/datawatcher/configuration.py +0 -2
- tomwer/gui/control/datawatcher/datawatcher.py +23 -13
- tomwer/gui/control/datawatcher/datawatcherobserver.py +1 -1
- tomwer/gui/control/observations.py +0 -3
- tomwer/gui/control/selectorwidgetbase.py +42 -12
- tomwer/gui/control/serie/seriecreator.py +967 -0
- tomwer/{web/__init__.py → gui/control/serie/seriewaiter.py} +5 -7
- tomwer/gui/control/singletomoobj.py +15 -4
- tomwer/gui/control/test/test_datalist.py +1 -1
- tomwer/gui/control/test/test_datalistener.py +1 -1
- tomwer/gui/control/test/test_inputwidget.py +1 -1
- tomwer/gui/control/test/test_process_manager.py +1 -13
- tomwer/gui/control/test/test_scanselector.py +1 -1
- tomwer/gui/control/test/test_scanvalidator.py +1 -1
- tomwer/gui/control/test/test_single_tomo_obj.py +1 -1
- tomwer/gui/control/test/test_volume_dialog.py +19 -7
- tomwer/gui/control/test/test_volumeselector.py +4 -4
- tomwer/gui/debugtools/datasetgenerator.py +1 -9
- tomwer/gui/edit/dkrfpatch.py +2 -3
- tomwer/gui/edit/imagekeyeditor.py +12 -11
- tomwer/gui/edit/nxtomoeditor.py +475 -0
- tomwer/gui/edit/test/test_dkrf_patch.py +2 -14
- tomwer/gui/edit/test/test_image_key_editor.py +2 -2
- tomwer/gui/edit/test/test_nx_editor.py +155 -0
- tomwer/gui/icons.py +0 -1
- tomwer/gui/qfolderdialog.py +11 -0
- tomwer/gui/reconstruction/axis/CompareImages.py +27 -29
- tomwer/gui/reconstruction/axis/axis.py +2 -0
- tomwer/gui/reconstruction/axis/radioaxis.py +70 -14
- tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +7 -9
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +22 -24
- tomwer/gui/reconstruction/lamino/tofu/projections.py +1 -1
- tomwer/gui/reconstruction/lamino/tofu/tofu.py +3 -3
- tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +4 -4
- tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +10 -5
- tomwer/gui/reconstruction/nabu/castvolume.py +103 -24
- tomwer/gui/reconstruction/nabu/check.py +1 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +352 -0
- tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +0 -9
- tomwer/gui/reconstruction/nabu/nabuconfig/output.py +1 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +18 -19
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +30 -7
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +26 -15
- tomwer/gui/reconstruction/nabu/slices.py +10 -4
- tomwer/gui/reconstruction/nabu/slurm.py +1 -1
- tomwer/gui/reconstruction/nabu/volume.py +13 -7
- tomwer/gui/reconstruction/normalization/intensity.py +1 -5
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +10 -37
- tomwer/gui/reconstruction/saaxis/saaxis.py +11 -7
- tomwer/gui/reconstruction/saaxis/sliceselector.py +11 -26
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +13 -8
- tomwer/gui/reconstruction/scores/scoreplot.py +67 -62
- tomwer/gui/reconstruction/test/test_axis.py +2 -2
- tomwer/gui/reconstruction/test/test_lamino.py +2 -2
- tomwer/gui/reconstruction/test/test_nabu.py +14 -1
- tomwer/gui/reconstruction/test/test_saaxis.py +8 -17
- tomwer/gui/reconstruction/test/test_sadeltabeta.py +7 -13
- tomwer/gui/stackplot.py +11 -28
- tomwer/gui/test/test_axis_gui.py +4 -4
- tomwer/gui/test/test_qfolder_dialog.py +12 -0
- tomwer/gui/utils/inputwidget.py +42 -22
- tomwer/gui/utils/lineselector/lineselector.py +13 -21
- tomwer/gui/utils/scandescription.py +2 -4
- tomwer/gui/utils/slider.py +1 -102
- tomwer/gui/utils/unitsystem.py +48 -11
- tomwer/gui/visualization/dataviewer.py +24 -17
- tomwer/gui/visualization/diffviewer/diffviewer.py +2 -11
- tomwer/gui/visualization/nxtomometadata.py +21 -0
- tomwer/gui/visualization/scanoverview.py +0 -1
- tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +72 -0
- tomwer/gui/visualization/test/test_stacks.py +1 -1
- tomwer/gui/visualization/tomoobjoverview.py +49 -0
- tomwer/gui/visualization/volumeoverview.py +64 -0
- tomwer/gui/visualization/volumeviewer.py +1 -1
- tomwer/io/utils/utils.py +2 -2
- tomwer/resources/gui/icons/multi-document-save.png +0 -0
- tomwer/resources/gui/icons/multi-document-save.svg +101 -0
- tomwer/resources/gui/illustrations/ctf_z1.png +0 -0
- tomwer/resources/gui/illustrations/ctf_z1.svg +471 -0
- tomwer/synctools/axis.py +0 -1
- tomwer/synctools/darkref.py +0 -1
- tomwer/synctools/datalistener.py +5 -1
- tomwer/synctools/imageloaderthread.py +2 -2
- tomwer/synctools/saaxis.py +0 -1
- tomwer/synctools/sadeltabeta.py +0 -1
- tomwer/synctools/stacks/edit/imagekeyeditor.py +1 -1
- tomwer/synctools/stacks/processingstack.py +2 -2
- tomwer/synctools/stacks/reconstruction/castvolume.py +1 -0
- tomwer/synctools/stacks/reconstruction/dkrefcopy.py +1 -1
- tomwer/synctools/stacks/reconstruction/lamino.py +1 -3
- tomwer/synctools/stacks/reconstruction/sadeltabeta.py +0 -2
- tomwer/synctools/test/test_darkRefs.py +32 -149
- tomwer/synctools/test/test_foldertransfer.py +1 -1
- tomwer/synctools/test/test_scanstages.py +2 -2
- tomwer/tests/conftest.py +51 -0
- tomwer/{test → tests}/test_scripts.py +1 -1
- tomwer/tests/test_utils.py +10 -0
- tomwer/{test → tests}/utils/utilstest.py +0 -11
- tomwer/version.py +3 -3
- {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/METADATA +14 -16
- {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/RECORD +255 -235
- {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/WHEEL +1 -1
- {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/entry_points.txt +6 -0
- orangecontrib/tomwer/setup.py +0 -45
- orangecontrib/tomwer/widgets/setup.py +0 -49
- tomwer/app/process.py +0 -153
- tomwer/core/process/reconstruction/nabu/slurm.py +0 -36
- tomwer/core/process/reconstruction/utils/nabu_slice_exec.py +0 -10
- tomwer/core/utils/laminoutils.py +0 -80
- tomwer/gui/utils/lineselector/lineselection.py +0 -76
- tomwer/setup.py +0 -52
- tomwer/slurm/executor.py +0 -36
- tomwer/slurm/job.py +0 -349
- tomwer/slurm/utils.py +0 -44
- tomwer/web/client.py +0 -43
- tomwer/web/config.py +0 -36
- tomwer/web/test/test_graylog_connection.py +0 -59
- {tomwer/slurm → orangecontrib/tomwer/tutorials}/__init__.py +0 -0
- /tomwer/{test → gui/control/serie}/__init__.py +0 -0
- /tomwer/{web/test → tests}/__init__.py +0 -0
- /tomwer/{test → tests}/utils/__init__.py +0 -0
- /tomwer-1.0.3-py3.8-nspkg.pth → /tomwer-1.1.0-py3.9-nspkg.pth +0 -0
- {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/LICENSE +0 -0
- {tomwer-1.0.3.dist-info → tomwer-1.1.0.dist-info}/namespace_packages.txt +0 -0
- {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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|