tomwer 1.2.0a1__py3-none-any.whl → 1.2.0a3__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/append_raw_darks_and_flats_frames_to_NXtomos.ows +44 -0
- orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth1.ows +55 -0
- orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth2.ows +48 -0
- orangecontrib/tomwer/tutorials/default_cor_search.ows +40 -0
- orangecontrib/tomwer/tutorials/hello_world_python_script.ows +50 -0
- orangecontrib/tomwer/tutorials/simple_slice_reconstruction_on_slurm.ows +50 -0
- orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +8 -8
- orangecontrib/tomwer/widgets/__init__.py +1 -1
- orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +0 -1
- orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +8 -6
- orangecontrib/tomwer/widgets/control/AdvancementOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +1 -6
- orangecontrib/tomwer/widgets/control/DataListOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataListenerOW.py +4 -4
- orangecontrib/tomwer/widgets/control/DataSelectorOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataTransfertOW.py +7 -7
- orangecontrib/tomwer/widgets/control/DataValidatorOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataWatcherOW.py +0 -3
- orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +3 -2
- orangecontrib/tomwer/widgets/control/EmailOW.py +82 -0
- orangecontrib/tomwer/widgets/control/FilterOW.py +3 -3
- orangecontrib/tomwer/widgets/control/NXTomomillOW.py +1 -1
- orangecontrib/tomwer/widgets/control/NotifierOW.py +0 -1
- orangecontrib/tomwer/widgets/control/ReduceDarkFlatSelectorOW.py +93 -0
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +29 -5
- orangecontrib/tomwer/widgets/control/TimerOW.py +1 -2
- orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +0 -1
- orangecontrib/tomwer/widgets/control/VolumeSelector.py +0 -1
- orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +4 -10
- orangecontrib/tomwer/widgets/control/icons/email.png +0 -0
- orangecontrib/tomwer/widgets/control/icons/email.svg +58 -0
- orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.png +0 -0
- orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.svg +199 -0
- orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +0 -1
- orangecontrib/tomwer/widgets/debugtools/ObjectInspectorOW.py +0 -1
- orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +1 -2
- orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +1 -2
- orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +0 -1
- orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +0 -1
- orangecontrib/tomwer/widgets/other/PythonScriptOW.py +29 -1
- orangecontrib/tomwer/widgets/other/TomoObjsHub.py +28 -0
- orangecontrib/tomwer/widgets/other/icons/hub.png +0 -0
- orangecontrib/tomwer/widgets/other/icons/hub.svg +113 -0
- orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +18 -12
- orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +0 -2
- orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +21 -6
- orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +29 -7
- orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +18 -5
- orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +40 -13
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +37 -10
- orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +2 -3
- orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +5 -4
- orangecontrib/tomwer/widgets/stitching/StitcherOW.py +0 -1
- orangecontrib/tomwer/widgets/stitching/ZStitchingConfigOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +10 -4
- orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/RadioStackOW.py +7 -5
- orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -3
- orangecontrib/tomwer/widgets/visualization/SliceStackOW.py +7 -5
- orangecontrib/tomwer/widgets/visualization/VolumeViewerOW.py +4 -4
- tomwer/__main__.py +139 -5
- tomwer/app/axis.py +16 -5
- tomwer/app/canvas_launcher/config.py +1 -1
- tomwer/app/canvas_launcher/mainwindow.py +164 -6
- tomwer/app/darkref.py +10 -181
- tomwer/app/darkrefpatch.py +10 -131
- tomwer/app/diffframe.py +11 -0
- tomwer/app/imagekeyeditor.py +12 -19
- tomwer/app/intensitynormalization.py +1 -0
- tomwer/app/lamino.py +7 -2
- tomwer/app/patchrawdarkflat.py +131 -0
- tomwer/app/radiostack.py +10 -0
- tomwer/app/reducedarkflat.py +205 -0
- tomwer/app/saaxis.py +27 -8
- tomwer/app/sadeltabeta.py +29 -8
- tomwer/app/samplemoved.py +11 -0
- tomwer/app/scanviewer.py +12 -0
- tomwer/app/sinogramviewer.py +11 -0
- tomwer/app/slicestack.py +11 -0
- tomwer/app/zstitching.py +12 -0
- tomwer/core/futureobject.py +4 -2
- tomwer/core/process/conditions/filters.py +26 -4
- tomwer/core/process/control/datadiscovery.py +4 -0
- tomwer/core/process/control/datawatcher/datawatcher.py +5 -1
- tomwer/core/process/control/email.py +148 -0
- tomwer/core/process/control/nxtomoconcatenate.py +9 -2
- tomwer/core/process/control/nxtomomill.py +58 -16
- tomwer/core/process/control/scanselector.py +4 -0
- tomwer/core/process/control/scantransfer.py +52 -23
- tomwer/core/process/control/test/test_concatenate_nxtomos.py +1 -0
- tomwer/core/process/control/test/test_email.py +52 -0
- tomwer/core/process/control/test/test_h52nx_process.py +106 -0
- tomwer/core/process/control/test/test_volume_link.py +5 -4
- tomwer/core/process/control/timer.py +27 -6
- tomwer/core/process/control/tomoobjserie.py +4 -0
- tomwer/core/process/control/volumeselector.py +4 -0
- tomwer/core/process/control/volumesymlink.py +47 -8
- tomwer/core/process/edit/darkflatpatch.py +49 -8
- tomwer/core/process/edit/imagekeyeditor.py +63 -13
- tomwer/core/process/reconstruction/axis/__init__.py +1 -1
- tomwer/core/process/reconstruction/axis/axis.py +61 -41
- tomwer/core/process/reconstruction/axis/params.py +4 -6
- tomwer/core/process/reconstruction/darkref/darkrefs.py +53 -16
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +12 -2
- tomwer/core/process/reconstruction/lamino/__init__.py +1 -1
- tomwer/core/process/reconstruction/lamino/tofu.py +22 -2
- tomwer/core/process/reconstruction/nabu/nabucommon.py +93 -14
- tomwer/core/process/reconstruction/nabu/nabuscores.py +70 -33
- tomwer/core/process/reconstruction/nabu/nabuslices.py +219 -41
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +240 -108
- tomwer/core/process/reconstruction/nabu/utils.py +10 -36
- tomwer/core/process/reconstruction/normalization/normalization.py +10 -3
- tomwer/core/process/reconstruction/saaxis/__init__.py +1 -0
- tomwer/core/process/reconstruction/saaxis/saaxis.py +564 -376
- tomwer/core/process/reconstruction/sadeltabeta/__init__.py +1 -0
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +481 -268
- tomwer/core/process/reconstruction/scores/params.py +21 -8
- tomwer/core/process/reconstruction/test/test_darkref_copy.py +2 -0
- tomwer/core/process/reconstruction/test/test_saaxis.py +21 -8
- tomwer/core/process/reconstruction/test/test_sadeltabeta.py +8 -5
- tomwer/core/process/script/python.py +7 -2
- tomwer/core/process/stitching/nabustitcher.py +10 -3
- tomwer/core/process/task.py +2 -9
- tomwer/core/process/test/test_axis.py +25 -15
- tomwer/core/process/test/test_conditions.py +6 -6
- tomwer/core/process/test/test_dark_and_flat.py +20 -15
- tomwer/core/process/test/test_data_transfer.py +8 -8
- tomwer/core/process/test/test_data_watcher.py +1 -1
- tomwer/core/process/test/test_lamino.py +6 -6
- tomwer/core/process/test/test_nabu.py +13 -8
- tomwer/core/process/test/test_normalization.py +1 -0
- tomwer/core/process/test/test_timer.py +6 -6
- tomwer/core/process/visualization/dataviewer.py +4 -0
- tomwer/core/process/visualization/diffviewer.py +4 -0
- tomwer/core/process/visualization/imagestackviewer.py +4 -0
- tomwer/core/process/visualization/radiostack.py +4 -0
- tomwer/core/process/visualization/samplemoved.py +4 -0
- tomwer/core/process/visualization/sinogramviewer.py +4 -0
- tomwer/core/process/visualization/slicestack.py +4 -0
- tomwer/core/process/visualization/volumeviewer.py +4 -0
- tomwer/core/scan/hdf5scan.py +4 -4
- tomwer/core/scan/scanbase.py +5 -1
- tomwer/core/scan/test/test_process_registration.py +9 -9
- tomwer/core/settings.py +59 -1
- tomwer/core/test/test_lamino.py +2 -1
- tomwer/core/utils/__init__.py +16 -0
- tomwer/core/utils/locker.py +0 -1
- tomwer/core/utils/resource.py +6 -11
- tomwer/core/utils/scanutils.py +2 -0
- tomwer/gui/cluster/slurm.py +91 -7
- tomwer/gui/cluster/supervisor.py +16 -11
- tomwer/gui/cluster/test/test_cluster.py +16 -1
- tomwer/gui/conditions/filter.py +3 -3
- tomwer/gui/control/datalist.py +24 -11
- tomwer/gui/control/email.py +183 -0
- tomwer/gui/control/reducedarkflatselector.py +545 -0
- tomwer/gui/control/singletomoobj.py +23 -1
- tomwer/gui/control/test/test_email.py +35 -0
- tomwer/gui/control/test/test_reducedarkflat_selector.py +280 -0
- tomwer/gui/reconstruction/axis/CompareImages.py +1 -1
- tomwer/gui/reconstruction/axis/axis.py +10 -6
- tomwer/gui/reconstruction/axis/radioaxis.py +14 -6
- tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +2 -0
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +4 -4
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +3 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +34 -33
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +1 -1
- tomwer/gui/reconstruction/normalization/intensity.py +5 -5
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +1 -0
- tomwer/gui/reconstruction/saaxis/saaxis.py +6 -6
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +6 -6
- tomwer/gui/reconstruction/scores/scoreplot.py +6 -4
- tomwer/gui/samplemoved/__init__.py +2 -2
- tomwer/gui/stackplot.py +18 -7
- tomwer/gui/stacks.py +2 -2
- tomwer/gui/stitching/stitchandbackground.py +2 -2
- tomwer/gui/stitching/stitching.py +1 -1
- tomwer/gui/stitching/stitching_raw.py +1 -1
- tomwer/gui/utils/__init__.py +1 -85
- tomwer/gui/utils/illustrations.py +1 -1
- tomwer/gui/utils/inputwidget.py +41 -36
- tomwer/gui/utils/slider.py +2 -2
- tomwer/gui/utils/utils.py +93 -0
- tomwer/gui/visualization/dataviewer.py +8 -5
- tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
- tomwer/gui/visualization/reconstructionparameters.py +26 -6
- tomwer/gui/visualization/sinogramviewer.py +7 -1
- tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -4
- tomwer/gui/visualization/volumeviewer.py +2 -0
- tomwer/resources/__init__.py +55 -43
- tomwer/resources/gui/icons/compose.png +0 -0
- tomwer/resources/gui/icons/compose.svg +75 -0
- tomwer/synctools/datatransfert.py +3 -1
- tomwer/synctools/stacks/edit/darkflatpatch.py +39 -34
- tomwer/synctools/stacks/edit/imagekeyeditor.py +8 -27
- tomwer/synctools/stacks/processingstack.py +45 -9
- tomwer/synctools/stacks/reconstruction/axis.py +6 -5
- tomwer/synctools/stacks/reconstruction/dkrefcopy.py +1 -0
- tomwer/synctools/stacks/reconstruction/lamino.py +3 -3
- tomwer/synctools/stacks/reconstruction/nabu.py +49 -140
- tomwer/synctools/stacks/reconstruction/normalization.py +1 -0
- tomwer/synctools/stacks/reconstruction/saaxis.py +19 -33
- tomwer/synctools/stacks/reconstruction/sadeltabeta.py +16 -32
- tomwer/synctools/test/test_darkRefs.py +19 -10
- tomwer/synctools/test/test_foldertransfer.py +7 -7
- tomwer/third_party/nabu/preproc/phase.py +6 -8
- tomwer/third_party/nabu/utils.py +2 -3
- tomwer/version.py +1 -1
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/METADATA +15 -54
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/RECORD +219 -192
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/WHEEL +1 -1
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/entry_points.txt +3 -3
- /tomwer-1.2.0a1-py3.9-nspkg.pth → /tomwer-1.2.0a3-py3.11-nspkg.pth +0 -0
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/LICENSE +0 -0
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/top_level.txt +0 -0
@@ -127,7 +127,7 @@ class TestNabuIni(unittest.TestCase):
|
|
127
127
|
# check volume and slice .cfg files for nabu reconstruction are here
|
128
128
|
for file_name in (
|
129
129
|
os.path.basename(self.scan.path) + ".cfg",
|
130
|
-
os.path.basename(self.scan.path) + "
|
130
|
+
os.path.basename(self.scan.path) + "slice_000001" + ".cfg",
|
131
131
|
):
|
132
132
|
with self.subTest(file_name=file_name):
|
133
133
|
self.assertTrue(
|
@@ -151,7 +151,7 @@ class TestNabuIni(unittest.TestCase):
|
|
151
151
|
# check volume and slice .cfg files for nabu reconstruction are here
|
152
152
|
for file_name in (
|
153
153
|
os.path.basename(self.scan.path) + "pag_db0100.cfg",
|
154
|
-
os.path.basename(self.scan.path) + "
|
154
|
+
os.path.basename(self.scan.path) + "slice_pag_000001_db0100" + ".cfg",
|
155
155
|
):
|
156
156
|
with self.subTest(file_name=file_name):
|
157
157
|
self.assertTrue(
|
@@ -178,7 +178,7 @@ class TestNabuIni(unittest.TestCase):
|
|
178
178
|
ini_files.append(
|
179
179
|
os.path.basename(self.scan.path)
|
180
180
|
+ "slice_"
|
181
|
-
+ str(slice_index).zfill(
|
181
|
+
+ str(slice_index).zfill(6)
|
182
182
|
+ ".cfg"
|
183
183
|
)
|
184
184
|
|
@@ -222,7 +222,7 @@ class TestNabuIni(unittest.TestCase):
|
|
222
222
|
# add slice ini file
|
223
223
|
ini_files.append(
|
224
224
|
os.path.basename(self.scan.path)
|
225
|
-
+ "
|
225
|
+
+ "slice_pag_000001_db"
|
226
226
|
+ str(int(pag_db)).zfill(4)
|
227
227
|
+ ".cfg"
|
228
228
|
)
|
@@ -265,7 +265,7 @@ class TestNabuIni(unittest.TestCase):
|
|
265
265
|
ini_files.append(
|
266
266
|
os.path.basename(self.scan.path)
|
267
267
|
+ "slice_pag_"
|
268
|
-
+ str(slice_index).zfill(
|
268
|
+
+ str(slice_index).zfill(6)
|
269
269
|
+ "_db"
|
270
270
|
+ str(pag_db).zfill(4)
|
271
271
|
+ ".cfg"
|
@@ -365,9 +365,14 @@ class TestNabuAndAxis(unittest.TestCase):
|
|
365
365
|
# initial configuration
|
366
366
|
self.conf = get_nabu_default_config(output_dir=self.scan.path)
|
367
367
|
|
368
|
-
self.nabu_process = nabu.
|
369
|
-
|
370
|
-
|
368
|
+
self.nabu_process = nabu.NabuSlicesTask(
|
369
|
+
inputs={
|
370
|
+
"data": self.scan,
|
371
|
+
"nabu_params": self.conf,
|
372
|
+
"dry_run": True,
|
373
|
+
"serialize_output_data": False,
|
374
|
+
},
|
375
|
+
)
|
371
376
|
self.scan._axis_params = AxisRP()
|
372
377
|
self.nabu_cfg_folder = os.path.join(
|
373
378
|
self.scan.path, nabu_settings.NABU_CFG_FILE_FOLDER
|
@@ -32,7 +32,7 @@ import shutil
|
|
32
32
|
import tempfile
|
33
33
|
import unittest
|
34
34
|
|
35
|
-
from tomwer.core.process.control.timer import
|
35
|
+
from tomwer.core.process.control.timer import TimerTask
|
36
36
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
37
37
|
from tomwer.core.utils.scanutils import MockEDF
|
38
38
|
|
@@ -53,25 +53,25 @@ class TestTimerIO(unittest.TestCase):
|
|
53
53
|
def testInputOutput(self):
|
54
54
|
"""Test that io using TomoBase instance work"""
|
55
55
|
for input_type in (dict, TomwerScanBase):
|
56
|
-
for
|
56
|
+
for serialize_output_data in (True, False):
|
57
57
|
with self.subTest(
|
58
|
-
return_dict=
|
58
|
+
return_dict=serialize_output_data,
|
59
59
|
input_type=input_type,
|
60
60
|
):
|
61
61
|
input_obj = self.scan
|
62
62
|
if input_obj is dict:
|
63
63
|
input_obj = input_obj.to_dict()
|
64
64
|
|
65
|
-
timer_process =
|
65
|
+
timer_process = TimerTask(
|
66
66
|
inputs={
|
67
67
|
"wait": 0.1,
|
68
|
-
"
|
68
|
+
"serialize_output_data": serialize_output_data,
|
69
69
|
"data": input_obj,
|
70
70
|
}
|
71
71
|
)
|
72
72
|
timer_process.run()
|
73
73
|
out = timer_process.outputs.data
|
74
|
-
if
|
74
|
+
if serialize_output_data:
|
75
75
|
self.assertTrue(isinstance(out, dict))
|
76
76
|
else:
|
77
77
|
self.assertTrue(isinstance(out, TomwerScanBase))
|
@@ -31,5 +31,9 @@ from ewokscore.task import Task as EwoksTask
|
|
31
31
|
|
32
32
|
|
33
33
|
class _DataViewerPlaceHolder(EwoksTask, input_names=("data",)):
|
34
|
+
"""
|
35
|
+
Task to browse a scan and associated processing (display raw frames, normalized projections, recosntructed slices...)
|
36
|
+
"""
|
37
|
+
|
34
38
|
def run(self):
|
35
39
|
pass
|
tomwer/core/scan/hdf5scan.py
CHANGED
@@ -311,10 +311,10 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
|
|
311
311
|
if self._reduced_darks is None:
|
312
312
|
if self.process_file is not None and os.path.exists(self.process_file):
|
313
313
|
from tomwer.core.process.reconstruction.darkref.darkrefs import (
|
314
|
-
|
314
|
+
DarkRefsTask,
|
315
315
|
) # avoid cyclic import
|
316
316
|
|
317
|
-
reduced_darks =
|
317
|
+
reduced_darks = DarkRefsTask.get_darks_frm_process_file(
|
318
318
|
process_file=self.process_file, entry=self.entry
|
319
319
|
)
|
320
320
|
if reduced_darks is not None:
|
@@ -326,10 +326,10 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
|
|
326
326
|
if self._reduced_flats is None:
|
327
327
|
if self.process_file is not None and os.path.exists(self.process_file):
|
328
328
|
from tomwer.core.process.reconstruction.darkref.darkrefs import (
|
329
|
-
|
329
|
+
DarkRefsTask,
|
330
330
|
) # avoid cyclic import
|
331
331
|
|
332
|
-
reduced_flats =
|
332
|
+
reduced_flats = DarkRefsTask.get_flats_frm_process_file(
|
333
333
|
process_file=self.process_file, entry=self.entry
|
334
334
|
)
|
335
335
|
if reduced_flats is not None:
|
tomwer/core/scan/scanbase.py
CHANGED
@@ -411,7 +411,11 @@ class TomwerScanBase(TomwerObject):
|
|
411
411
|
res = {}
|
412
412
|
# nabu reconstruction parameters
|
413
413
|
if self._nabu_params:
|
414
|
-
res[self._DICT_NABU_RP_KEY] =
|
414
|
+
res[self._DICT_NABU_RP_KEY] = (
|
415
|
+
self.nabu_recons_params
|
416
|
+
if isinstance(self.nabu_recons_params, dict)
|
417
|
+
else self.nabu_recons_params.to_dict()
|
418
|
+
)
|
415
419
|
else:
|
416
420
|
res[self._DICT_NABU_RP_KEY] = None
|
417
421
|
# axis reconstruction parameters
|
@@ -68,55 +68,55 @@ class TestProcessRegistration(unittest.TestCase):
|
|
68
68
|
shutil.rmtree(self.tmp_dir)
|
69
69
|
|
70
70
|
def testGetCorValues(self):
|
71
|
-
from tomwer.core.process.reconstruction.axis import
|
71
|
+
from tomwer.core.process.reconstruction.axis import AxisTask
|
72
72
|
|
73
73
|
for i in range(20):
|
74
74
|
results = {"center_of_rotation": i}
|
75
75
|
Task._register_process(
|
76
76
|
self.scan.process_file,
|
77
|
-
process=
|
77
|
+
process=AxisTask,
|
78
78
|
entry=self.scan.entry,
|
79
79
|
configuration=None,
|
80
80
|
results=results,
|
81
81
|
process_index=i,
|
82
82
|
)
|
83
|
-
cor_value =
|
83
|
+
cor_value = AxisTask.get_cor_frm_process_file(
|
84
84
|
self.scan.process_file, entry=self.scan.entry
|
85
85
|
)
|
86
86
|
self.assertEqual(cor_value, 19)
|
87
87
|
|
88
88
|
def testGetDarks(self):
|
89
|
-
from tomwer.core.process.reconstruction.darkref.darkrefs import
|
89
|
+
from tomwer.core.process.reconstruction.darkref.darkrefs import DarkRefsTask
|
90
90
|
|
91
91
|
for i in range(20):
|
92
92
|
results = {"darks": {"0": i * 2}, "flats": {"1": i}}
|
93
93
|
Task._register_process(
|
94
94
|
self.scan.process_file,
|
95
|
-
process=
|
95
|
+
process=DarkRefsTask,
|
96
96
|
entry=self.scan.entry,
|
97
97
|
configuration=None,
|
98
98
|
results=results,
|
99
99
|
process_index=i,
|
100
100
|
)
|
101
|
-
flats =
|
101
|
+
flats = DarkRefsTask.get_darks_frm_process_file(
|
102
102
|
self.scan.process_file, entry=self.scan.entry
|
103
103
|
)
|
104
104
|
self.assertEqual(flats[list(flats.keys())[0]], 19 * 2)
|
105
105
|
|
106
106
|
def testGetFlats(self):
|
107
|
-
from tomwer.core.process.reconstruction.darkref.darkrefs import
|
107
|
+
from tomwer.core.process.reconstruction.darkref.darkrefs import DarkRefsTask
|
108
108
|
|
109
109
|
for i in range(20):
|
110
110
|
results = {"darks": {"0": i}, "flats": {"1": i}}
|
111
111
|
Task._register_process(
|
112
112
|
self.scan.process_file,
|
113
|
-
process=
|
113
|
+
process=DarkRefsTask,
|
114
114
|
entry=self.scan.entry,
|
115
115
|
configuration=None,
|
116
116
|
results=results,
|
117
117
|
process_index=i,
|
118
118
|
)
|
119
|
-
flats =
|
119
|
+
flats = DarkRefsTask.get_flats_frm_process_file(
|
120
120
|
self.scan.process_file, entry=self.scan.entry
|
121
121
|
)
|
122
122
|
self.assertEqual(flats[list(flats.keys())[0]], 19)
|
tomwer/core/settings.py
CHANGED
@@ -29,6 +29,8 @@ __date__ = "02/06/2017"
|
|
29
29
|
|
30
30
|
|
31
31
|
import os
|
32
|
+
from silx.utils.enum import Enum as _Enum
|
33
|
+
|
32
34
|
|
33
35
|
__LBSRAM_PATH = '/lbsram'
|
34
36
|
|
@@ -84,8 +86,33 @@ def _set_dest_path(path):
|
|
84
86
|
__DEST_PATH = path
|
85
87
|
|
86
88
|
|
89
|
+
class SlurmSettingsMode(_Enum):
|
90
|
+
MANUAL = "manual"
|
91
|
+
GENERIC = "generic"
|
92
|
+
CAST_VOLUME = "cast_volume"
|
93
|
+
SLICE_RECONSTRUCTION = "slice_reconstruction"
|
94
|
+
VOLUME_RECONSTRUCTION = "volume_reconstruction"
|
95
|
+
|
96
|
+
@staticmethod
|
97
|
+
def get_settings_class(mode):
|
98
|
+
assert isinstance(mode, SlurmSettingsMode)
|
99
|
+
if mode is SlurmSettingsMode.MANUAL:
|
100
|
+
return None
|
101
|
+
elif mode is SlurmSettingsMode.GENERIC:
|
102
|
+
return SlurmSettings
|
103
|
+
elif mode is SlurmSettingsMode.CAST_VOLUME:
|
104
|
+
return DefaultSlurmSettingsCastVolume
|
105
|
+
elif mode is SlurmSettingsMode.SLICE_RECONSTRUCTION:
|
106
|
+
return DefaultSlurmSettingsSliceReconstruction
|
107
|
+
elif mode is SlurmSettingsMode.VOLUME_RECONSTRUCTION:
|
108
|
+
return DefaultSlurmSettingsVolumeReconstruction
|
109
|
+
else:
|
110
|
+
raise ValueError(f"{mode} not handled")
|
111
|
+
|
112
|
+
|
87
113
|
class SlurmSettings:
|
88
114
|
# Default slurm cluster configuration
|
115
|
+
|
89
116
|
N_CORES_PER_TASK = 4
|
90
117
|
"""Number of CPU per worker"""
|
91
118
|
|
@@ -95,7 +122,7 @@ class SlurmSettings:
|
|
95
122
|
N_JOBS = 1
|
96
123
|
"""on how many job we want to split the EwoksTask"""
|
97
124
|
|
98
|
-
MEMORY_PER_WORKER =
|
125
|
+
MEMORY_PER_WORKER = 64 # memory in GB
|
99
126
|
"""Amount of memory per worker"""
|
100
127
|
|
101
128
|
PARTITION = "p9gpu"
|
@@ -113,3 +140,34 @@ class SlurmSettings:
|
|
113
140
|
PROJECT_NAME = "tomwer_{scan}_-_{process}_-_{info}"
|
114
141
|
"""Slurm cluster project name. `scan`, `process` and `info` will be format.
|
115
142
|
"""
|
143
|
+
|
144
|
+
|
145
|
+
class DefaultSlurmSettingsCastVolume(SlurmSettings):
|
146
|
+
"""
|
147
|
+
default proposed configuration for casting a volume remotly
|
148
|
+
"""
|
149
|
+
N_GPUS_PER_WORKER = 0
|
150
|
+
|
151
|
+
N_CORES_PER_TASK = 8
|
152
|
+
|
153
|
+
MEMORY_PER_WORKER = 128 # memory in GB
|
154
|
+
|
155
|
+
PARTITION = "nice*"
|
156
|
+
|
157
|
+
|
158
|
+
class DefaultSlurmSettingsSliceReconstruction(SlurmSettings):
|
159
|
+
"""
|
160
|
+
default proposed configuration for reconstructing a single slice remotly
|
161
|
+
"""
|
162
|
+
MEMORY_PER_WORKER = 256 # memory in GB
|
163
|
+
|
164
|
+
PARTITION = None
|
165
|
+
|
166
|
+
|
167
|
+
class DefaultSlurmSettingsVolumeReconstruction(SlurmSettings):
|
168
|
+
"""
|
169
|
+
default proposed configuration for reconstructing a full volume remotly
|
170
|
+
"""
|
171
|
+
MEMORY_PER_WORKER = 256 # memory in GB
|
172
|
+
|
173
|
+
PARTITION = None
|
tomwer/core/test/test_lamino.py
CHANGED
@@ -44,7 +44,7 @@ class TestTofuReconstruction(unittest.TestCase):
|
|
44
44
|
def setUp(self):
|
45
45
|
self._scan_path = tempfile.mkdtemp()
|
46
46
|
self.scan = EDFTomoScan(self._scan_path)
|
47
|
-
self.reconstruction = tofu.
|
47
|
+
self.reconstruction = tofu.LaminoReconstructionTask(
|
48
48
|
inputs={
|
49
49
|
"dry_run": True,
|
50
50
|
"data": self.scan,
|
@@ -53,6 +53,7 @@ class TestTofuReconstruction(unittest.TestCase):
|
|
53
53
|
"projections": "tata-yoyo",
|
54
54
|
"output": "output_dir",
|
55
55
|
},
|
56
|
+
"serialize_output_data": False,
|
56
57
|
}
|
57
58
|
)
|
58
59
|
|
tomwer/core/utils/__init__.py
CHANGED
@@ -448,3 +448,19 @@ def DownloadDataset(dataset, output_folder, timeout, unpack=False):
|
|
448
448
|
if unpack is True:
|
449
449
|
shutil.unpack_archive(archive_folder, extract_dir=output_folder, format="bztar")
|
450
450
|
os.remove(archive_folder)
|
451
|
+
|
452
|
+
|
453
|
+
def concatenate_dict(dict_1, dict_2) -> dict:
|
454
|
+
"""update dict which has dict as values. And we want concatenate those values to"""
|
455
|
+
res = dict_1.copy()
|
456
|
+
for key in dict_2:
|
457
|
+
if key in dict_1:
|
458
|
+
if key in [f"axis_{axis}_params" for axis in (0, 1, 2)]:
|
459
|
+
res[key] = ";".join((dict_1[key], dict_2[key]))
|
460
|
+
elif isinstance(dict_1[key], dict):
|
461
|
+
res[key] = concatenate_dict(dict_1=dict_1[key], dict_2=dict_2[key])
|
462
|
+
else:
|
463
|
+
res.update({key: dict_2[key]})
|
464
|
+
else:
|
465
|
+
res[key] = dict_2[key]
|
466
|
+
return res
|
tomwer/core/utils/locker.py
CHANGED
@@ -81,6 +81,5 @@ class FileLockerManager:
|
|
81
81
|
# from pathlib import Path
|
82
82
|
# Path(lock_file_path).touch()
|
83
83
|
if lock_file_path not in _FILE_LOCKERS:
|
84
|
-
print("create lock to", lock_file_path)
|
85
84
|
_FILE_LOCKERS[lock_file_path] = Lock(lock_file_path, default_timeout=3)
|
86
85
|
return _FILE_LOCKERS[lock_file_path]
|
tomwer/core/utils/resource.py
CHANGED
@@ -27,6 +27,7 @@ __license__ = "MIT"
|
|
27
27
|
__date__ = "25/11/2021"
|
28
28
|
|
29
29
|
import logging
|
30
|
+
import resource
|
30
31
|
|
31
32
|
_logger = logging.getLogger(__name__)
|
32
33
|
|
@@ -34,15 +35,9 @@ _logger = logging.getLogger(__name__)
|
|
34
35
|
def increase_max_number_file():
|
35
36
|
"""increase the maximal number of file the software can open within respect of the hard limit"""
|
36
37
|
try:
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
hard_nofile = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
39
|
+
resource.setrlimit(resource.RLIMIT_NOFILE, (hard_nofile, hard_nofile))
|
40
|
+
except (ValueError, OSError):
|
41
|
+
_logger.warning("Failed to retrieve and set the max opened files limit")
|
40
42
|
else:
|
41
|
-
|
42
|
-
try:
|
43
|
-
hard_nofile = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
44
|
-
resource.setrlimit(resource.RLIMIT_NOFILE, (hard_nofile, hard_nofile))
|
45
|
-
except (ValueError, OSError):
|
46
|
-
_logger.warning("Failed to retrieve and set the max opened files limit")
|
47
|
-
else:
|
48
|
-
_logger.debug("Set max opened files to %d", hard_nofile)
|
43
|
+
_logger.debug("Set max opened files to %d", hard_nofile)
|
tomwer/core/utils/scanutils.py
CHANGED
@@ -407,6 +407,8 @@ def data_identifier_to_scan(data_identifier: Any):
|
|
407
407
|
"""
|
408
408
|
if isinstance(data_identifier, str):
|
409
409
|
return ScanFactory.create_tomo_object_from_identifier(data_identifier)
|
410
|
+
elif isinstance(data_identifier, dict):
|
411
|
+
return ScanFactory.create_scan_object_frm_dict(data_identifier)
|
410
412
|
else:
|
411
413
|
return data_identifier
|
412
414
|
|
tomwer/gui/cluster/slurm.py
CHANGED
@@ -33,7 +33,8 @@ from typing import Optional
|
|
33
33
|
from silx.gui import qt
|
34
34
|
from sluurp.utils import get_partitions
|
35
35
|
|
36
|
-
from tomwer.core.settings import SlurmSettings
|
36
|
+
from tomwer.core.settings import SlurmSettings, SlurmSettingsMode
|
37
|
+
from tomwer.gui.utils.qt_utils import block_signals
|
37
38
|
|
38
39
|
|
39
40
|
class SlurmSettingsDialog(qt.QDialog):
|
@@ -44,7 +45,8 @@ class SlurmSettingsDialog(qt.QDialog):
|
|
44
45
|
super().__init__(parent=parent)
|
45
46
|
|
46
47
|
self.setLayout(qt.QVBoxLayout())
|
47
|
-
self._mainWidget =
|
48
|
+
self._mainWidget = SlurmSettingsWindow(parent=self)
|
49
|
+
self._mainWidget.setWindowFlags(qt.Qt.Widget)
|
48
50
|
self.layout().addWidget(self._mainWidget)
|
49
51
|
|
50
52
|
# buttons for validation
|
@@ -71,6 +73,88 @@ class SlurmSettingsDialog(qt.QDialog):
|
|
71
73
|
self._mainWidget.setConfiguration(config=config)
|
72
74
|
|
73
75
|
|
76
|
+
class SlurmSettingsWindow(qt.QMainWindow):
|
77
|
+
"""
|
78
|
+
Main window to define slurm settings.
|
79
|
+
Composed of the SlurmSettingsWidget and a combobox with some predefined settings
|
80
|
+
"""
|
81
|
+
|
82
|
+
sigConfigChanged = qt.Signal()
|
83
|
+
"""Signal emit when the SlurmSetting changed"""
|
84
|
+
|
85
|
+
def __init__(self, parent: Optional[qt.QWidget] = None) -> None:
|
86
|
+
super().__init__(parent)
|
87
|
+
self._mainWidget = qt.QWidget(self)
|
88
|
+
self._mainWidget.setLayout(qt.QFormLayout())
|
89
|
+
|
90
|
+
self._modeCombox = qt.QComboBox(self)
|
91
|
+
self._mainWidget.layout().addRow("configuration: ", self._modeCombox)
|
92
|
+
self._modeCombox.addItems(SlurmSettingsMode.values())
|
93
|
+
self._modeCombox.setCurrentText(SlurmSettingsMode.GENERIC.value)
|
94
|
+
|
95
|
+
self._settingsWidget = SlurmSettingsWidget(self)
|
96
|
+
self._mainWidget.layout().addRow(self._settingsWidget)
|
97
|
+
|
98
|
+
self.setCentralWidget(self._mainWidget)
|
99
|
+
|
100
|
+
# set up
|
101
|
+
self._reloadPredefinedSettings()
|
102
|
+
|
103
|
+
# connect signal / slot
|
104
|
+
self._modeCombox.currentIndexChanged.connect(self._reloadPredefinedSettings)
|
105
|
+
self._settingsWidget.sigConfigChanged.connect(self._configChanged)
|
106
|
+
# when the settings widget is edited them we automatically move to 'manual' settings. To notify visually the user
|
107
|
+
self._settingsWidget.sigConfigChanged.connect(self._switchToManual)
|
108
|
+
|
109
|
+
def _reloadPredefinedSettings(self, *args, **kkwargs):
|
110
|
+
"""
|
111
|
+
reload settings from some predefined configuration
|
112
|
+
"""
|
113
|
+
mode = self.getCurrentSettingsMode()
|
114
|
+
settingsClass = SlurmSettingsMode.get_settings_class(mode)
|
115
|
+
if settingsClass:
|
116
|
+
with block_signals(self._settingsWidget):
|
117
|
+
self.setConfiguration(
|
118
|
+
{
|
119
|
+
"cpu-per-task": settingsClass.N_CORES_PER_TASK,
|
120
|
+
"n_tasks": settingsClass.N_TASKS,
|
121
|
+
"n_jobs": settingsClass.N_JOBS,
|
122
|
+
"memory": settingsClass.MEMORY_PER_WORKER,
|
123
|
+
"partition": settingsClass.PARTITION,
|
124
|
+
"n_gpus": settingsClass.N_GPUS_PER_WORKER,
|
125
|
+
"job_name": settingsClass.PROJECT_NAME,
|
126
|
+
"walltime": settingsClass.DEFAULT_WALLTIME,
|
127
|
+
"python_venv": settingsClass.PYTHON_VENV,
|
128
|
+
}
|
129
|
+
)
|
130
|
+
|
131
|
+
def _configChanged(self, *args, **kwargs):
|
132
|
+
self.sigConfigChanged.emit()
|
133
|
+
|
134
|
+
def _switchToManual(self):
|
135
|
+
self._modeCombox.setCurrentText(SlurmSettingsMode.MANUAL.value)
|
136
|
+
|
137
|
+
def getCurrentSettingsMode(self) -> SlurmSettingsMode:
|
138
|
+
return SlurmSettingsMode.from_value(self._modeCombox.currentText())
|
139
|
+
|
140
|
+
def setCurrentSettingsMode(self, mode: SlurmSettingsMode) -> SlurmSettingsMode:
|
141
|
+
mode = SlurmSettingsMode.from_value(mode)
|
142
|
+
self._modeCombox.setCurrentText(mode.value)
|
143
|
+
|
144
|
+
# expose API
|
145
|
+
def getConfiguration(self) -> dict:
|
146
|
+
return self._settingsWidget.getConfiguration()
|
147
|
+
|
148
|
+
def getSlurmClusterConfiguration(self) -> dict:
|
149
|
+
return self._settingsWidget.getSlurmClusterConfiguration()
|
150
|
+
|
151
|
+
def setConfiguration(self, config: dict) -> None:
|
152
|
+
self._settingsWidget.setConfiguration(config=config)
|
153
|
+
|
154
|
+
def isSlurmActive(self):
|
155
|
+
return self._settingsWidget.isSlurmActive()
|
156
|
+
|
157
|
+
|
74
158
|
class SlurmSettingsWidget(qt.QWidget):
|
75
159
|
"""Widget used to define Slurm configuration to be used"""
|
76
160
|
|
@@ -212,19 +296,19 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
212
296
|
return self._nCores.value()
|
213
297
|
|
214
298
|
def setNCores(self, n: int) -> None:
|
215
|
-
self._nCores.setValue(n)
|
299
|
+
self._nCores.setValue(int(n))
|
216
300
|
|
217
301
|
def getNWorkers(self) -> int:
|
218
302
|
return self._nWorkers.value()
|
219
303
|
|
220
304
|
def setNWorkers(self, n) -> None:
|
221
|
-
self._nWorkers.setValue(n)
|
305
|
+
self._nWorkers.setValue(int(n))
|
222
306
|
|
223
307
|
def getMemory(self) -> int:
|
224
308
|
return self._memory.value()
|
225
309
|
|
226
310
|
def setMemory(self, memory: int) -> None:
|
227
|
-
self._memory.setValue(memory)
|
311
|
+
self._memory.setValue(int(memory))
|
228
312
|
|
229
313
|
def getQueue(self) -> str:
|
230
314
|
return self._queue.currentText()
|
@@ -236,13 +320,13 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
236
320
|
return self._nGpu.value()
|
237
321
|
|
238
322
|
def setNGPU(self, n: int) -> None:
|
239
|
-
self._nGpu.setValue(n)
|
323
|
+
self._nGpu.setValue(int(n))
|
240
324
|
|
241
325
|
def getNJobs(self) -> int:
|
242
326
|
return self._nJobs.value()
|
243
327
|
|
244
328
|
def setNJobs(self, value: int):
|
245
|
-
self._nJobs.setValue(value)
|
329
|
+
self._nJobs.setValue(int(value))
|
246
330
|
|
247
331
|
def getProjectName(self):
|
248
332
|
return self._jobName.text()
|