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/core/utils/scanutils.py
CHANGED
@@ -29,10 +29,12 @@ __authors__ = ["H. Payno"]
|
|
29
29
|
__license__ = "MIT"
|
30
30
|
__date__ = "11/08/2022"
|
31
31
|
|
32
|
+
import logging
|
32
33
|
import h5py
|
33
34
|
import numpy
|
34
35
|
import time
|
35
36
|
import os
|
37
|
+
from typing import Any
|
36
38
|
from tomoscan.io import HDF5File
|
37
39
|
from tomoscan.esrf.scan.mock import MockEDF as _MockEDF, MockHDF5 as _MockHDF5
|
38
40
|
from tomoscan.test.utils import MockContext
|
@@ -41,6 +43,8 @@ from tomwer.core.scan.hdf5scan import HDF5TomoScan
|
|
41
43
|
from tomwer.core.scan.scanfactory import ScanFactory
|
42
44
|
from silx.io.utils import h5py_read_dataset
|
43
45
|
|
46
|
+
_logger = logging.getLogger(__name__)
|
47
|
+
|
44
48
|
|
45
49
|
class MockHDF5(_MockHDF5):
|
46
50
|
def __init__(self, *args, **kwargs):
|
@@ -391,3 +395,49 @@ class HDF5MockContext(MockContext, mock_class=MockHDF5):
|
|
391
395
|
return MockHDF5(
|
392
396
|
scan_path=self._scan_path, n_proj=self._n_proj, **self._mocks_params
|
393
397
|
).scan
|
398
|
+
|
399
|
+
|
400
|
+
def data_identifier_to_scan(data_identifier: Any):
|
401
|
+
"""
|
402
|
+
from a identifier (as str) try to create a scan.
|
403
|
+
Mostly used when 'data' parameter is set from ewoks. In this case we expect it to be a (string) identifier
|
404
|
+
"""
|
405
|
+
if isinstance(data_identifier, str):
|
406
|
+
return ScanFactory.create_tomo_object_from_identifier(data_identifier)
|
407
|
+
else:
|
408
|
+
return data_identifier
|
409
|
+
|
410
|
+
|
411
|
+
def format_output_location(location: str, scan):
|
412
|
+
"""
|
413
|
+
format possible keys from the location like {scan_dir} or {scan_path}
|
414
|
+
|
415
|
+
:param location:
|
416
|
+
:param scan:
|
417
|
+
:return:
|
418
|
+
"""
|
419
|
+
if scan is None:
|
420
|
+
_logger.warning("scan is !none, enable to format the nabu output location")
|
421
|
+
|
422
|
+
keywords = {
|
423
|
+
"scan_dir_name": scan.scan_dir_name(),
|
424
|
+
"scan_basename": scan.scan_basename(),
|
425
|
+
"scan_parent_dir_basename": scan.scan_parent_dir_basename(),
|
426
|
+
}
|
427
|
+
|
428
|
+
# filter necessary keywords
|
429
|
+
def get_necessary_keywords():
|
430
|
+
import string
|
431
|
+
|
432
|
+
formatter = string.Formatter()
|
433
|
+
return [field for _, field, _, _ in formatter.parse(location) if field]
|
434
|
+
|
435
|
+
requested_keywords = get_necessary_keywords()
|
436
|
+
|
437
|
+
def keyword_needed(pair):
|
438
|
+
keyword, _ = pair
|
439
|
+
return keyword in requested_keywords
|
440
|
+
|
441
|
+
keywords = dict(filter(keyword_needed, keywords.items()))
|
442
|
+
location = os.path.abspath(location.format(**keywords))
|
443
|
+
return location
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from tomwer.core.volume.volumefactory import VolumeFactory
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
|
5
|
+
def volume_identifier_to_volume(volume_identifier: Any):
|
6
|
+
"""
|
7
|
+
from a str identifier try to create a volume.
|
8
|
+
Mostly used when 'volume' parameter is set from ewoks. In this case we expect it to be a (string) identifier
|
9
|
+
"""
|
10
|
+
if isinstance(volume_identifier, str):
|
11
|
+
return VolumeFactory.create_tomo_object_from_identifier(volume_identifier)
|
12
|
+
else:
|
13
|
+
return volume_identifier
|
tomwer/core/volume/edfvolume.py
CHANGED
@@ -49,6 +49,10 @@ class EDFVolumeIdentifier(_EDFVolumeIdentifier, DatasetIdentifier):
|
|
49
49
|
ObjClass=EDFVolume,
|
50
50
|
)
|
51
51
|
|
52
|
+
def long_description(self) -> str:
|
53
|
+
"""used for processview header tooltip for now"""
|
54
|
+
return self.to_str()
|
55
|
+
|
52
56
|
|
53
57
|
class EDFVolume(_EDFVolume, TomwerVolumeBase, Dataset):
|
54
58
|
@staticmethod
|
tomwer/core/volume/hdf5volume.py
CHANGED
@@ -69,6 +69,10 @@ class HDF5VolumeIdentifier(_HDF5VolumeIdentifier, DatasetIdentifier):
|
|
69
69
|
raise ValueError("expects to get a data_path")
|
70
70
|
return HDF5VolumeIdentifier(object=HDF5Volume, hdf5_file=hdf5_file, entry=entry)
|
71
71
|
|
72
|
+
def long_description(self) -> str:
|
73
|
+
"""used for processview header tooltip for now"""
|
74
|
+
return self.to_str()
|
75
|
+
|
72
76
|
|
73
77
|
class HDF5Volume(_HDF5Volume, TomwerVolumeBase, Dataset):
|
74
78
|
@staticmethod
|
tomwer/core/volume/jp2kvolume.py
CHANGED
@@ -51,6 +51,10 @@ class JP2KVolumeIdentifier(_JP2KVolumeIdentifier, DatasetIdentifier):
|
|
51
51
|
ObjClass=JP2KVolume,
|
52
52
|
)
|
53
53
|
|
54
|
+
def long_description(self) -> str:
|
55
|
+
"""used for processview header tooltip for now"""
|
56
|
+
return self.to_str()
|
57
|
+
|
54
58
|
|
55
59
|
class JP2KVolume(_JP2KVolume, TomwerVolumeBase, Dataset):
|
56
60
|
@staticmethod
|
tomwer/core/volume/rawvolume.py
CHANGED
@@ -34,6 +34,10 @@ from tomoscan.esrf.identifier.rawidentifier import (
|
|
34
34
|
RawVolumeIdentifier as _RawVolumeIdentifier,
|
35
35
|
)
|
36
36
|
from processview.core.dataset import DatasetIdentifier, Dataset
|
37
|
+
from urllib.parse import urlparse
|
38
|
+
from tomoscan.esrf.identifier.url_utils import (
|
39
|
+
split_path,
|
40
|
+
)
|
37
41
|
|
38
42
|
|
39
43
|
class RawVolumeIdentifier(_RawVolumeIdentifier, DatasetIdentifier):
|
@@ -45,11 +49,24 @@ class RawVolumeIdentifier(_RawVolumeIdentifier, DatasetIdentifier):
|
|
45
49
|
|
46
50
|
@staticmethod
|
47
51
|
def from_str(identifier):
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
info = urlparse(identifier)
|
53
|
+
paths = split_path(info.path)
|
54
|
+
if len(paths) == 1:
|
55
|
+
vol_file = paths[0]
|
56
|
+
tomo_type = None
|
57
|
+
elif len(paths) == 2:
|
58
|
+
tomo_type, vol_file = paths
|
59
|
+
else:
|
60
|
+
raise ValueError("Failed to parse path string:", info.path)
|
61
|
+
if tomo_type is not None and tomo_type != RawVolumeIdentifier.TOMO_TYPE:
|
62
|
+
raise TypeError(
|
63
|
+
f"provided identifier fits {tomo_type} and not {RawVolumeIdentifier.TOMO_TYPE}"
|
64
|
+
)
|
65
|
+
return RawVolumeIdentifier(object=RawVolume, file_path=vol_file)
|
66
|
+
|
67
|
+
def long_description(self) -> str:
|
68
|
+
"""used for processview header tooltip for now"""
|
69
|
+
return self.to_str()
|
53
70
|
|
54
71
|
|
55
72
|
class RawVolume(_RawVolume, TomwerVolumeBase, Dataset):
|
tomwer/core/volume/tiffvolume.py
CHANGED
@@ -54,6 +54,10 @@ class TIFFVolumeIdentifier(_TIFFVolumeIdentifier, DatasetIdentifier):
|
|
54
54
|
ObjClass=TIFFVolume,
|
55
55
|
)
|
56
56
|
|
57
|
+
def long_description(self) -> str:
|
58
|
+
"""used for processview header tooltip for now"""
|
59
|
+
return self.to_str()
|
60
|
+
|
57
61
|
|
58
62
|
class MultiTiffVolumeIdentifier(_MultiTiffVolumeIdentifier, DatasetIdentifier):
|
59
63
|
def __init__(self, object, tiff_file):
|
tomwer/core/volume/volumebase.py
CHANGED
@@ -3,14 +3,12 @@ from tomwer.core.tomwer_object import TomwerObject
|
|
3
3
|
|
4
4
|
|
5
5
|
class TomwerVolumeBase(TomwerObject):
|
6
|
-
def get_identifier(self):
|
7
|
-
return self.get_identifier()
|
8
|
-
|
9
6
|
def _clear_heavy_cache(self):
|
10
7
|
"""util user"""
|
11
8
|
self.data = None
|
12
9
|
self.metadata = None
|
13
10
|
|
11
|
+
@staticmethod
|
14
12
|
def format_output_location(location: str, volume):
|
15
13
|
if not isinstance(volume, TomwerVolumeBase):
|
16
14
|
raise TypeError(
|
@@ -20,20 +18,29 @@ class TomwerVolumeBase(TomwerObject):
|
|
20
18
|
keywords = {
|
21
19
|
"volume_data_parent_folder": volume.volume_data_parent_folder(),
|
22
20
|
}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
|
22
|
+
# filter necessary keywords
|
23
|
+
def get_necessary_keywords():
|
24
|
+
import string
|
25
|
+
|
26
|
+
formatter = string.Formatter()
|
27
|
+
return [field for _, field, _, _ in formatter.parse(location) if field]
|
28
|
+
|
29
|
+
requested_keywords = get_necessary_keywords()
|
30
|
+
|
31
|
+
def keyword_needed(pair):
|
32
|
+
keyword, _ = pair
|
33
|
+
return keyword in requested_keywords
|
34
|
+
|
35
|
+
keywords = dict(filter(keyword_needed, keywords.items()))
|
36
|
+
location = os.path.abspath(location.format(**keywords))
|
30
37
|
return location
|
31
38
|
|
32
39
|
def volume_data_parent_folder(self):
|
33
|
-
if self.data_url is None:
|
40
|
+
if self.data_url is None: # pylint: disable=E1101
|
34
41
|
raise ValueError("data_url doesn't exists")
|
35
42
|
else:
|
36
|
-
return os.path.dirname(self.data_url.file_path())
|
43
|
+
return os.path.dirname(self.data_url.file_path()) # pylint: disable=E1101
|
37
44
|
|
38
45
|
def __str__(self) -> str:
|
39
46
|
try:
|
@@ -28,6 +28,7 @@ __license__ = "MIT"
|
|
28
28
|
__date__ = "13/07/2022"
|
29
29
|
|
30
30
|
|
31
|
+
from typing import Optional
|
31
32
|
from urllib.parse import urlparse
|
32
33
|
from typing import Union
|
33
34
|
from tomoscan.factory import Factory as _oVolumeFactory
|
@@ -60,6 +61,22 @@ _logger = logging.getLogger(__name__)
|
|
60
61
|
|
61
62
|
|
62
63
|
class VolumeFactory(_oVolumeFactory):
|
64
|
+
@staticmethod
|
65
|
+
def from_identifier_to_vol_urls(identifier) -> Optional[tuple]:
|
66
|
+
"""
|
67
|
+
convert an identifier to a volume
|
68
|
+
and return all the existing url of this volume
|
69
|
+
"""
|
70
|
+
try:
|
71
|
+
vol = VolumeFactory.create_tomo_object_from_identifier(
|
72
|
+
identifier=identifier
|
73
|
+
)
|
74
|
+
except Exception as e:
|
75
|
+
_logger.error(e)
|
76
|
+
return None
|
77
|
+
else:
|
78
|
+
return tuple(vol.browse_data_urls())
|
79
|
+
|
63
80
|
@docstring(_oVolumeFactory.create_tomo_object_from_identifier)
|
64
81
|
@staticmethod
|
65
82
|
def create_tomo_object_from_identifier(identifier: Union[str, BaseIdentifier]):
|
@@ -74,7 +91,9 @@ class VolumeFactory(_oVolumeFactory):
|
|
74
91
|
:rtype: tomwer.core.scan.scanbase.TomwerScanBase
|
75
92
|
:raises: ValueError if scan_path is not containing a scan
|
76
93
|
"""
|
77
|
-
if
|
94
|
+
if isinstance(identifier, BaseIdentifier):
|
95
|
+
identifier = identifier.to_str()
|
96
|
+
elif not isinstance(identifier, str):
|
78
97
|
raise TypeError(
|
79
98
|
f"identifier is expected to be a str or an instance of {BaseIdentifier} not {type(identifier)}"
|
80
99
|
)
|
tomwer/gui/cluster/slurm.py
CHANGED
@@ -162,7 +162,7 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
162
162
|
self._nCores.setValue(SlurmSettings.N_CORES_PER_TASK)
|
163
163
|
self._nWorkers.setValue(SlurmSettings.N_TASKS)
|
164
164
|
self._memory.setValue(SlurmSettings.MEMORY_PER_WORKER)
|
165
|
-
self._queue.setText(SlurmSettings.
|
165
|
+
self._queue.setText(SlurmSettings.PARTITION)
|
166
166
|
self._nGpu.setValue(SlurmSettings.N_GPUS_PER_WORKER)
|
167
167
|
self._jobName.setText(SlurmSettings.PROJECT_NAME)
|
168
168
|
self._wallTimeQLE.setText(SlurmSettings.DEFAULT_WALLTIME)
|
tomwer/gui/cluster/supervisor.py
CHANGED
@@ -178,7 +178,6 @@ class _DatasetProcessModel(qt.QAbstractTableModel):
|
|
178
178
|
return future_scan.status in self._filteredStatus
|
179
179
|
|
180
180
|
def _computeUnfilteredFutureTomoObjs(self):
|
181
|
-
|
182
181
|
i_row = 0
|
183
182
|
self._filteredFutureTomoObjs = OrderedDict()
|
184
183
|
|
@@ -368,7 +367,6 @@ class FilterWidget(qt.QGroupBox):
|
|
368
367
|
"""signal emit when filter change"""
|
369
368
|
|
370
369
|
def __init__(self, parent=None):
|
371
|
-
|
372
370
|
super().__init__("show job with status", parent)
|
373
371
|
self.setLayout(qt.QHBoxLayout())
|
374
372
|
# spacer
|
@@ -31,7 +31,7 @@ from tomwer.gui.reconstruction.nabu.slurm import SlurmSettingsWidget
|
|
31
31
|
from tomwer.core.settings import SlurmSettings
|
32
32
|
from silx.gui.utils.testutils import TestCaseQt
|
33
33
|
from silx.gui import qt
|
34
|
-
from tomwer.
|
34
|
+
from tomwer.tests.utils import skip_gui_test
|
35
35
|
import pytest
|
36
36
|
|
37
37
|
|
@@ -54,7 +54,7 @@ class TestSlurmWidget(TestCaseQt):
|
|
54
54
|
"cpu-per-task": SlurmSettings.N_CORES_PER_TASK,
|
55
55
|
"n_tasks": SlurmSettings.N_TASKS,
|
56
56
|
"memory": SlurmSettings.MEMORY_PER_WORKER,
|
57
|
-
"partition": SlurmSettings.
|
57
|
+
"partition": SlurmSettings.PARTITION,
|
58
58
|
"n_gpus": SlurmSettings.N_GPUS_PER_WORKER,
|
59
59
|
}
|
60
60
|
assert dict_res == expected_dict, f"{dict_res} vs {expected_dict}"
|
tomwer/gui/control/datalist.py
CHANGED
@@ -66,6 +66,7 @@ from nxtomomill.io.config import TomoHDF5Config as HDF5Config
|
|
66
66
|
from nxtomomill.io.config import TomoEDFConfig as EDFConfig
|
67
67
|
from nxtomomill.io import generate_default_edf_config
|
68
68
|
from nxtomomill.io import generate_default_h5_config
|
69
|
+
from tomwer.gui.utils.qt_utils import block_signals
|
69
70
|
|
70
71
|
logger = logging.getLogger(__name__)
|
71
72
|
|
@@ -222,9 +223,6 @@ class _NXtomomillConfigFileDialog(qt.QDialog):
|
|
222
223
|
def accept(self):
|
223
224
|
self.hide()
|
224
225
|
|
225
|
-
def _createDefaultConfigFile(self):
|
226
|
-
raise NotImplementedError
|
227
|
-
|
228
226
|
def _createConfigFileSelector(self):
|
229
227
|
raise NotImplementedError
|
230
228
|
|
@@ -245,7 +243,7 @@ class BlissHDF5DataListDialog(_DataListDialog):
|
|
245
243
|
def createDataList(self):
|
246
244
|
return BlissScanList(self)
|
247
245
|
|
248
|
-
def _callbackAddPath(self):
|
246
|
+
def _callbackAddPath(self): # pragma: no cover
|
249
247
|
""" """
|
250
248
|
dialog = qt.QFileDialog(self)
|
251
249
|
dialog.setNameFilters(["HDF5 file *.h5 *.hdf5 *.nx *.nexus", "nxs"])
|
@@ -280,7 +278,7 @@ class EDFDataListDialog(_DataListDialog):
|
|
280
278
|
def createDataList(self):
|
281
279
|
return EDFDataList(self)
|
282
280
|
|
283
|
-
def _callbackAddPath(self):
|
281
|
+
def _callbackAddPath(self): # pragma: no cover
|
284
282
|
""" """
|
285
283
|
dialog = qt.QFileDialog(self)
|
286
284
|
dialog.setFileMode(qt.QFileDialog.DirectoryOnly)
|
@@ -300,7 +298,6 @@ class EDFDataListDialog(_DataListDialog):
|
|
300
298
|
|
301
299
|
|
302
300
|
class _RawDataListMainWindow(qt.QMainWindow):
|
303
|
-
|
304
301
|
sigNXTomoCFGFileChanged = qt.Signal(str)
|
305
302
|
"""signal emitted when the configuration file change"""
|
306
303
|
|
@@ -409,14 +406,14 @@ class _RawDataListMainWindow(qt.QMainWindow):
|
|
409
406
|
else:
|
410
407
|
return config
|
411
408
|
|
412
|
-
def createNXtomomillConfigFileDialog(self):
|
409
|
+
def createNXtomomillConfigFileDialog(self): # pragma: no cover
|
413
410
|
file_dialog = qt.QFileDialog()
|
414
411
|
file_dialog.setAcceptMode(qt.QFileDialog.AcceptSave)
|
415
412
|
file_dialog.setWindowTitle("Select file path to save configuration file")
|
416
413
|
file_dialog.setNameFilters(
|
417
414
|
[
|
418
415
|
"Any file (*)",
|
419
|
-
"Configuration file (*.txt *.cfg *.conf)",
|
416
|
+
"Configuration file (*.txt *.cfg *.conf *.config)",
|
420
417
|
]
|
421
418
|
)
|
422
419
|
file_dialog.setFileMode(qt.QFileDialog.AnyFile)
|
@@ -443,7 +440,7 @@ class BlissHDF5DataListMainWindow(_RawDataListMainWindow):
|
|
443
440
|
**kwargs,
|
444
441
|
)
|
445
442
|
|
446
|
-
def _createNewConfigFile(self):
|
443
|
+
def _createNewConfigFile(self): # pragma: no cover
|
447
444
|
file_dialog = self.createNXtomomillConfigFileDialog()
|
448
445
|
if file_dialog.exec_():
|
449
446
|
files_selected = file_dialog.selectedFiles()
|
@@ -478,7 +475,7 @@ class EDFDataListMainWindow(_RawDataListMainWindow):
|
|
478
475
|
**kwargs,
|
479
476
|
)
|
480
477
|
|
481
|
-
def _createNewConfigFile(self):
|
478
|
+
def _createNewConfigFile(self): # pragma: no cover
|
482
479
|
file_dialog = self.createNXtomomillConfigFileDialog()
|
483
480
|
if file_dialog.exec_():
|
484
481
|
files_selected = file_dialog.selectedFiles()
|
@@ -499,7 +496,7 @@ class GenericScanListDialog(_DataListDialog):
|
|
499
496
|
def createDataList(self):
|
500
497
|
return GenericScanList(self)
|
501
498
|
|
502
|
-
def _callbackAddPath(self):
|
499
|
+
def _callbackAddPath(self): # pragma: no cover
|
503
500
|
""" """
|
504
501
|
dialog = QDataDialog(self, multiSelection=True)
|
505
502
|
dialog.setNameFilters(
|
@@ -528,7 +525,7 @@ class VolumeListDialog(_DataListDialog):
|
|
528
525
|
def createDataList(self):
|
529
526
|
return VolumeList(self)
|
530
527
|
|
531
|
-
def _callbackAddPath(self):
|
528
|
+
def _callbackAddPath(self): # pragma: no cover
|
532
529
|
""" """
|
533
530
|
dialog = QVolumeDialog(self)
|
534
531
|
|
@@ -544,13 +541,15 @@ class VolumeListDialog(_DataListDialog):
|
|
544
541
|
|
545
542
|
|
546
543
|
class _TomwerObjectList(qt.QTableWidget):
|
547
|
-
|
548
544
|
HEADER_NAMES = ("undefined object",)
|
549
545
|
|
550
546
|
dataReady = qt.Signal(TomwerObject)
|
551
547
|
|
548
|
+
listChanged = qt.Signal()
|
549
|
+
"""emit when containt of the list changed"""
|
550
|
+
|
552
551
|
def __init__(self, parent):
|
553
|
-
self.
|
552
|
+
self._copy_target = None
|
554
553
|
qt.QTableWidget.__init__(self, parent)
|
555
554
|
self.setRowCount(0)
|
556
555
|
self.setColumnCount(1)
|
@@ -564,12 +563,17 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
564
563
|
self.setAcceptDrops(True)
|
565
564
|
|
566
565
|
self._myitems = OrderedDict()
|
566
|
+
# key is the TomoObject identifier and value is the QTableWidgetItem.
|
567
|
+
# Text is the identifier, QTableWidgetItem data under UserRole is the TomoObject object
|
567
568
|
|
568
569
|
# QMenu
|
569
570
|
self.menu = qt.QMenu(self)
|
570
571
|
self._copyAction = qt.QAction("copy")
|
571
572
|
self._copyAction.triggered.connect(self._copyRequested)
|
573
|
+
self._pasteAction = qt.QAction("paste")
|
574
|
+
self._pasteAction.triggered.connect(self._pasteRequested)
|
572
575
|
self.menu.addAction(self._copyAction)
|
576
|
+
self.menu.addAction(self._pasteAction)
|
573
577
|
|
574
578
|
def n_data(self):
|
575
579
|
return len(self._myitems)
|
@@ -610,6 +614,7 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
610
614
|
else:
|
611
615
|
item = self._myitems[identifier_as_str]
|
612
616
|
self.remove_item(item)
|
617
|
+
self.listChanged.emit()
|
613
618
|
|
614
619
|
def _update(self):
|
615
620
|
tomwer_objects = [
|
@@ -617,9 +622,11 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
617
622
|
for identifier_as_str in self._myitems.keys()
|
618
623
|
]
|
619
624
|
self.clear()
|
620
|
-
|
621
|
-
|
625
|
+
with block_signals(self):
|
626
|
+
for tomwer_object in tomwer_objects:
|
627
|
+
self.add(tomwer_object)
|
622
628
|
self.sortByColumn(0, self.horizontalHeader().sortIndicatorOrder())
|
629
|
+
self.listChanged.emit()
|
623
630
|
|
624
631
|
def _getTomoObject(self, obj: str):
|
625
632
|
"""
|
@@ -667,7 +674,8 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
667
674
|
# in this case we will update the value. Because if the same identifier already exists at launch time
|
668
675
|
# it will create two different objects that could be an issue.
|
669
676
|
# this is better to have it unified
|
670
|
-
|
677
|
+
with block_signals(self):
|
678
|
+
self.remove(self._myitems[identifier_as_str].data(qt.Qt.UserRole))
|
671
679
|
|
672
680
|
item = qt.QTableWidgetItem()
|
673
681
|
item.setText(identifier_as_str)
|
@@ -679,6 +687,7 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
679
687
|
self.setRowCount(row + 1)
|
680
688
|
self.setItem(row, 0, item)
|
681
689
|
self._myitems[identifier_as_str] = item
|
690
|
+
self.listChanged.emit()
|
682
691
|
return (obj,)
|
683
692
|
|
684
693
|
def setMySelection(self, datasets: tuple):
|
@@ -701,16 +710,18 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
701
710
|
def dropEvent(self, event):
|
702
711
|
if event.mimeData().hasFormat("text/uri-list"):
|
703
712
|
added_scans = set()
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
+
with block_signals(self):
|
714
|
+
for url in event.mimeData().urls():
|
715
|
+
new_scans = self.add(str(url.path()))
|
716
|
+
if new_scans is not None:
|
717
|
+
for new_scan in new_scans:
|
718
|
+
if not isinstance(new_scan, TomwerObject):
|
719
|
+
raise ValueError(
|
720
|
+
f"new_scan should be an instance of {TomwerObject} and not {type(new_scan)}"
|
721
|
+
)
|
722
|
+
added_scans.update(new_scans)
|
713
723
|
self.setMySelection(added_scans)
|
724
|
+
self.listChanged.emit()
|
714
725
|
|
715
726
|
def supportedDropActions(self):
|
716
727
|
"""Inherited method to redefine supported drop actions."""
|
@@ -744,13 +755,24 @@ class _TomwerObjectList(qt.QTableWidget):
|
|
744
755
|
return item.data(qt.Qt.UserRole)
|
745
756
|
|
746
757
|
def contextMenuEvent(self, event):
|
747
|
-
self.
|
748
|
-
|
749
|
-
|
758
|
+
self._copy_target = self._datasetAt(event.pos())
|
759
|
+
self._copyAction.setVisible(self._copy_target is not None)
|
760
|
+
self.menu.exec_(event.globalPos())
|
750
761
|
|
751
762
|
def _copyRequested(self):
|
752
763
|
clipboard = qt.QGuiApplication.clipboard()
|
753
|
-
|
764
|
+
if isinstance(self._copy_target, TomwerObject):
|
765
|
+
clipboard.setText(self._copy_target.get_identifier().to_str())
|
766
|
+
else:
|
767
|
+
clipboard.setText(str(self._copy_target))
|
768
|
+
|
769
|
+
def _pasteRequested(self):
|
770
|
+
clipboard = qt.QGuiApplication.clipboard()
|
771
|
+
identifier = clipboard.text()
|
772
|
+
try:
|
773
|
+
self.add(identifier)
|
774
|
+
except Exception as e:
|
775
|
+
logger.error(f"Failed to add {identifier}. Error is {e}")
|
754
776
|
|
755
777
|
|
756
778
|
class GenericScanList(_TomwerObjectList):
|
@@ -762,8 +784,12 @@ class GenericScanList(_TomwerObjectList):
|
|
762
784
|
"""
|
763
785
|
some rules to return a TomwerObject from an object (probably a path) from children class
|
764
786
|
"""
|
787
|
+
return self.getScanObject(obj)
|
788
|
+
|
789
|
+
@staticmethod
|
790
|
+
def getScanObject(obj):
|
765
791
|
if not isinstance(obj, str):
|
766
|
-
raise TypeError
|
792
|
+
raise TypeError(f"obj is an instance of {type(obj)} when {str} expected")
|
767
793
|
try:
|
768
794
|
scan_obj = ScanFactory.create_tomo_object_from_identifier(obj)
|
769
795
|
except ValueError as e1:
|
@@ -915,29 +941,76 @@ class VolumeList(_TomwerObjectList):
|
|
915
941
|
}
|
916
942
|
|
917
943
|
def _getTomoObject(self, obj: str):
|
944
|
+
return self.getVolumeObject(obj=obj)
|
945
|
+
|
946
|
+
@staticmethod
|
947
|
+
def getVolumeObject(obj, warn=True):
|
948
|
+
"""
|
949
|
+
get volume from identifier... even if not contained in the list of items (using factory)
|
950
|
+
"""
|
918
951
|
try:
|
919
952
|
tomo_obj = VolumeFactory.create_tomo_object_from_identifier(obj)
|
920
953
|
except Exception as e:
|
921
954
|
try:
|
922
|
-
tomo_obj = guess_volumes(
|
955
|
+
tomo_obj = guess_volumes(
|
956
|
+
obj, scheme_to_vol=VolumeList.DEFAULT_SCHEME_TO_VOL
|
957
|
+
)
|
923
958
|
except Exception:
|
924
|
-
|
959
|
+
if warn:
|
960
|
+
logger.warning(
|
961
|
+
f"Unable to create a volume from {obj}. Error is {e}"
|
962
|
+
)
|
925
963
|
return None
|
926
964
|
else:
|
965
|
+
# filter potential 'nabu histogram'
|
966
|
+
if tomo_obj is not None:
|
967
|
+
|
968
|
+
def is_not_histogram(vol_identifier):
|
969
|
+
return not (
|
970
|
+
hasattr(vol_identifier, "data_path")
|
971
|
+
and vol_identifier.data_path.endswith("histogram")
|
972
|
+
)
|
973
|
+
|
974
|
+
tomo_obj = tuple(filter(is_not_histogram, tomo_obj))
|
975
|
+
|
927
976
|
if tomo_obj is None or len(tomo_obj) == 0:
|
928
977
|
logger.warning(f"Unable to create a volume from {obj}.")
|
929
978
|
return None
|
930
979
|
else:
|
931
980
|
if len(tomo_obj) > 1:
|
932
|
-
|
933
|
-
|
934
|
-
|
981
|
+
if warn:
|
982
|
+
logger.warning(
|
983
|
+
f"more than one volume deduce from {obj}. Will only take the first one ({tomo_obj[0]})"
|
984
|
+
)
|
935
985
|
return tomo_obj[0]
|
936
986
|
else:
|
937
987
|
return tomo_obj
|
938
988
|
|
939
989
|
def getVolume(self, volume_id: str, default=None):
|
990
|
+
"""
|
991
|
+
get volume from id contained in the current items, else default
|
992
|
+
"""
|
940
993
|
if volume_id in self._myitems:
|
941
994
|
return self._myitems[volume_id].data(qt.Qt.UserRole)
|
942
995
|
else:
|
943
996
|
return default
|
997
|
+
|
998
|
+
|
999
|
+
class TomoObjList(_TomwerObjectList):
|
1000
|
+
HEADER_NAMES = ("tomo object",)
|
1001
|
+
|
1002
|
+
def _getTomoObject(self, obj: str):
|
1003
|
+
try:
|
1004
|
+
tomo_obj = VolumeList.getVolumeObject(obj=obj)
|
1005
|
+
except Exception:
|
1006
|
+
pass
|
1007
|
+
else:
|
1008
|
+
if tomo_obj not in (None, tuple()):
|
1009
|
+
return tomo_obj
|
1010
|
+
|
1011
|
+
try:
|
1012
|
+
tomo_obj = GenericScanList.getScanObject(obj=obj)
|
1013
|
+
except Exception:
|
1014
|
+
return None
|
1015
|
+
else:
|
1016
|
+
return tomo_obj
|
@@ -111,7 +111,7 @@ class DataTransfertSelector(qt.QWidget):
|
|
111
111
|
if b is True:
|
112
112
|
self.__updateFolder(None)
|
113
113
|
|
114
|
-
def _changeFolder(self):
|
114
|
+
def _changeFolder(self): # pragma: no cover
|
115
115
|
"""Callback when folder selection is choose"""
|
116
116
|
defaultDirectory = self._folderSelection.text()
|
117
117
|
if os.path.isdir(defaultDirectory):
|
@@ -36,7 +36,6 @@ from tomwer.core.process.control.datawatcher import status
|
|
36
36
|
|
37
37
|
|
38
38
|
class _DWConfigurationWidget(qt.QWidget):
|
39
|
-
|
40
39
|
startByOldestStateChanged = qt.Signal(bool)
|
41
40
|
|
42
41
|
def __init__(self, parent):
|
@@ -64,7 +63,6 @@ class _DWConfigurationWidget(qt.QWidget):
|
|
64
63
|
|
65
64
|
|
66
65
|
class _ObservationMethodSelector(qt.QWidget):
|
67
|
-
|
68
66
|
sigSelectionChanged = qt.Signal(tuple)
|
69
67
|
"""Return the selection made as a string and some information if needed in
|
70
68
|
a dictionary"""
|