tomwer 1.0.4__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +4 -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 -128
- orangecontrib/tomwer/widgets/control/NotifierOW.py +31 -7
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +3 -5
- orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +85 -0
- 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 +138 -0
- 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 -10
- 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 -18
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +24 -17
- 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/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 -3
- 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 +9 -18
- 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 -0
- 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 -1
- 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 +12 -1
- 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 +14 -4
- 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 +4 -0
- 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/test/test_cluster.py +2 -2
- tomwer/gui/control/datalist.py +109 -34
- tomwer/gui/control/datatransfert.py +1 -1
- 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 -11
- 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 -3
- 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 -8
- tomwer/gui/edit/dkrfpatch.py +2 -2
- tomwer/gui/edit/imagekeyeditor.py +12 -9
- 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/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 +67 -11
- 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 -4
- tomwer/gui/reconstruction/nabu/castvolume.py +80 -11
- 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 -13
- tomwer/gui/reconstruction/nabu/slices.py +10 -2
- tomwer/gui/reconstruction/nabu/slurm.py +1 -1
- tomwer/gui/reconstruction/nabu/volume.py +13 -7
- tomwer/gui/reconstruction/normalization/intensity.py +1 -1
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +10 -34
- tomwer/gui/reconstruction/saaxis/saaxis.py +11 -6
- tomwer/gui/reconstruction/saaxis/sliceselector.py +11 -26
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +13 -8
- tomwer/gui/reconstruction/scores/scoreplot.py +67 -61
- 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 -21
- 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/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/datalistener.py +5 -1
- tomwer/synctools/imageloaderthread.py +2 -2
- 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/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/__init__.py +0 -0
- 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.4.dist-info → tomwer-1.1.0.dist-info}/METADATA +14 -16
- {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/RECORD +245 -217
- {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/WHEEL +1 -1
- {tomwer-1.0.4.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/web/client.py +0 -43
- tomwer/web/config.py +0 -36
- tomwer/web/test/test_graylog_connection.py +0 -59
- {tomwer/test → orangecontrib/tomwer/tutorials}/__init__.py +0 -0
- /tomwer/{web/test → gui/control/serie}/__init__.py +0 -0
- /tomwer/{test → tests}/utils/__init__.py +0 -0
- /tomwer-1.0.4-py3.8-nspkg.pth → /tomwer-1.1.0-py3.9-nspkg.pth +0 -0
- {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/LICENSE +0 -0
- {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.0.4.dist-info → tomwer-1.1.0.dist-info}/top_level.txt +0 -0
@@ -35,20 +35,25 @@ __license__ = "MIT"
|
|
35
35
|
__date__ = "25/02/2021"
|
36
36
|
|
37
37
|
|
38
|
+
import os
|
39
|
+
import weakref
|
40
|
+
import numpy
|
41
|
+
import logging
|
42
|
+
from typing import Union
|
43
|
+
from contextlib import AbstractContextManager
|
44
|
+
from matplotlib import image as _matplotlib_image
|
38
45
|
from silx.gui import qt
|
39
46
|
from silx.gui.plot import PlotWidget
|
47
|
+
from tomwer.io.utils.utils import get_slice_data
|
40
48
|
from tomwer.gui.reconstruction.saaxis.dimensionwidget import DimensionWidget
|
41
49
|
from tomwer.gui.visualization.dataviewer import ImageStack
|
42
50
|
from tomwer.gui.utils.vignettes import VignettesQDialog
|
43
|
-
from contextlib import AbstractContextManager
|
44
51
|
from tomwer.gui.utils.buttons import PadlockButton
|
45
52
|
from tomwer.gui import icons
|
53
|
+
from tomwer.gui import settings
|
46
54
|
from tomwer.io.utils.h5pyutils import DatasetReader
|
47
55
|
from tomwer.core.process.reconstruction.scores.params import ScoreMethod
|
48
|
-
from
|
49
|
-
import weakref
|
50
|
-
import numpy
|
51
|
-
import logging
|
56
|
+
from tomwer.io.utils import get_default_directory
|
52
57
|
|
53
58
|
_logger = logging.getLogger(__name__)
|
54
59
|
|
@@ -310,7 +315,7 @@ class CorSelection(VariableSelection):
|
|
310
315
|
self._absoluteVarValueLE,
|
311
316
|
)
|
312
317
|
try:
|
313
|
-
import pyopencl # noqa F401
|
318
|
+
import pyopencl # noqa F401 pylint: disable=E0401
|
314
319
|
except Exception:
|
315
320
|
idx = self._scoreMethodCB.findText(ScoreMethod.TOMO_CONSISTENCY.value)
|
316
321
|
if idx >= 0:
|
@@ -495,10 +500,20 @@ class ScorePlot(qt.QWidget):
|
|
495
500
|
self.setLayout(qt.QGridLayout())
|
496
501
|
# main plot
|
497
502
|
self._plot = ImageStack(self, show_overview=False)
|
503
|
+
self._plot.getPlotWidget().setYAxisInverted(settings.Y_AXIS_DOWNWARD)
|
504
|
+
|
498
505
|
self._plot.getPlotWidget().setKeepDataAspectRatio(True)
|
499
506
|
self._plot._sliderDockWidget.hide()
|
500
507
|
self._plot.getPlotWidget().getColorBarWidget().hide()
|
501
508
|
self._plot.getPlotWidget().getPositionInfoWidget().hide()
|
509
|
+
# add save all action
|
510
|
+
save_all_icon = icons.getQIcon("multi-document-save")
|
511
|
+
self._saveAllSnapshot = qt.QAction(
|
512
|
+
save_all_icon, "save all screenshot as png", self
|
513
|
+
)
|
514
|
+
toolbar = self._plot.getPlotWidget().toolBar()
|
515
|
+
toolbar.addSeparator()
|
516
|
+
toolbar.addAction(self._saveAllSnapshot)
|
502
517
|
# hide dock widget
|
503
518
|
self._plot._reconsInfoDockWidget.hide()
|
504
519
|
self._plot._tableDockWidget.hide()
|
@@ -563,6 +578,7 @@ class ScorePlot(qt.QWidget):
|
|
563
578
|
self._varSelectedFromVignettes
|
564
579
|
)
|
565
580
|
self._varValueWidget.sigScoreMethodChanged.connect(self._updateScores)
|
581
|
+
self._saveAllSnapshot.triggered.connect(self._saveAllReconstructedSlices)
|
566
582
|
|
567
583
|
# set up
|
568
584
|
# for now we don't want to use the volume and voxel size
|
@@ -570,8 +586,8 @@ class ScorePlot(qt.QWidget):
|
|
570
586
|
self._voxelSizeW.hide()
|
571
587
|
self._axisLabel.hide()
|
572
588
|
|
573
|
-
def __init_subclass__(cls, constructor, **kwargs):
|
574
|
-
super().__init_subclass__(
|
589
|
+
def __init_subclass__(cls, constructor, **kwargs): # pylint: disable=E0302
|
590
|
+
super().__init_subclass__()
|
575
591
|
cls._CorSlectionBuilder = constructor
|
576
592
|
|
577
593
|
def getScoreMethod(self):
|
@@ -711,7 +727,8 @@ class ScorePlot(qt.QWidget):
|
|
711
727
|
self._plot.setUrls(urls=self._urls)
|
712
728
|
self._varSlider.setVarValues(self._var_values)
|
713
729
|
old = self._varSlider.blockSignals(True)
|
714
|
-
|
730
|
+
if len(self._var_values) > 0:
|
731
|
+
self._varSlider.setVarValue(self._var_values[0])
|
715
732
|
self._varSlider.blockSignals(old)
|
716
733
|
|
717
734
|
old = self._varValueWidget.blockSignals(True)
|
@@ -790,6 +807,47 @@ class ScorePlot(qt.QWidget):
|
|
790
807
|
)
|
791
808
|
)
|
792
809
|
|
810
|
+
def _saveAllReconstructedSlices(self): # pragma: no cover
|
811
|
+
"""
|
812
|
+
save all reconstructed slices to a folder provided by the user
|
813
|
+
"""
|
814
|
+
dialog = qt.QFileDialog(self, directory=get_default_directory())
|
815
|
+
dialog.setFileMode(qt.QFileDialog.DirectoryOnly)
|
816
|
+
if not dialog.exec_():
|
817
|
+
dialog.close()
|
818
|
+
return
|
819
|
+
|
820
|
+
output_folder = dialog.selectedFiles()[0]
|
821
|
+
try:
|
822
|
+
self.saveReconstructedSlicesTo(output_folder=output_folder)
|
823
|
+
except Exception as e:
|
824
|
+
_logger.error(f"Fail to save snapshots. Error is {e}")
|
825
|
+
else:
|
826
|
+
_logger.info(f"snapshots have been saved to {output_folder}")
|
827
|
+
|
828
|
+
def saveReconstructedSlicesTo(self, output_folder):
|
829
|
+
"""dump all slices with score as name"""
|
830
|
+
# make sure the output dir exists
|
831
|
+
os.makedirs(output_folder, exist_ok=True)
|
832
|
+
|
833
|
+
i_missing_score = 0
|
834
|
+
for score, slice_url in zip(self._var_values, self._urls):
|
835
|
+
try:
|
836
|
+
data = get_slice_data(slice_url)
|
837
|
+
if score is None:
|
838
|
+
file_name = f"no_score_{i_missing_score}.png"
|
839
|
+
i_missing_score += 1
|
840
|
+
else:
|
841
|
+
file_name = f"{score}.png"
|
842
|
+
_matplotlib_image.imsave(
|
843
|
+
os.path.join(output_folder, file_name),
|
844
|
+
data,
|
845
|
+
format="png",
|
846
|
+
)
|
847
|
+
|
848
|
+
except Exception as e:
|
849
|
+
_logger.error(f"Failed to dump {slice_url.path()}. Raison is {e}")
|
850
|
+
|
793
851
|
|
794
852
|
class _VarSlider(qt.QWidget):
|
795
853
|
def __init__(self, parent, orientation):
|
@@ -823,55 +881,3 @@ class _VarSlider(qt.QWidget):
|
|
823
881
|
|
824
882
|
def value(self):
|
825
883
|
return self._slider.value()
|
826
|
-
|
827
|
-
|
828
|
-
if __name__ == "__main__":
|
829
|
-
from silx.image.phantomgenerator import PhantomGenerator
|
830
|
-
from silx.io.url import DataUrl
|
831
|
-
import tempfile
|
832
|
-
import os
|
833
|
-
import h5py
|
834
|
-
import shutil
|
835
|
-
from scipy import stats
|
836
|
-
|
837
|
-
app = qt.QApplication([])
|
838
|
-
img_width = 216
|
839
|
-
data = PhantomGenerator.get2DPhantomSheppLogan(n=img_width)
|
840
|
-
nb_cor = 50
|
841
|
-
urls = []
|
842
|
-
slices_folder = tempfile.mkdtemp()
|
843
|
-
for i in range(nb_cor):
|
844
|
-
noise = (
|
845
|
-
numpy.random.random(img_width * img_width).reshape(img_width, img_width)
|
846
|
-
* 100.0
|
847
|
-
)
|
848
|
-
file_path = os.path.join(slices_folder, "slice_{}.hdf5".format(i))
|
849
|
-
with h5py.File(file_path, mode="a") as h5f:
|
850
|
-
h5f["data"] = noise + data
|
851
|
-
urls.append(DataUrl(file_path=file_path, data_path="data", scheme="silx"))
|
852
|
-
variance = 1
|
853
|
-
mu = 0.5
|
854
|
-
sigma = numpy.sqrt(variance)
|
855
|
-
x = numpy.linspace(mu - 3 * sigma, mu + 3 * sigma, nb_cor)
|
856
|
-
scores = stats.norm.pdf(x, mu, sigma)
|
857
|
-
|
858
|
-
cor_values = numpy.linspace(80, 120, nb_cor)
|
859
|
-
scores_dict = {}
|
860
|
-
for cor, url, score in zip(cor_values, urls, scores):
|
861
|
-
scores_dict[cor] = (url, score)
|
862
|
-
|
863
|
-
window1 = ScorePlot(variable_name="var x")
|
864
|
-
window1.setVarScores(scores=scores_dict, score_method="std")
|
865
|
-
window1.show()
|
866
|
-
from tomwer.core.scan.scanbase import TomwerScanBase
|
867
|
-
from tomwer.core.process.reconstruction.saaxis.params import SAAxisParams
|
868
|
-
from tomwer.core.process.reconstruction.saaxis.saaxis import SAAxisProcess
|
869
|
-
|
870
|
-
scan = TomwerScanBase()
|
871
|
-
scan.saaxis_params = SAAxisParams()
|
872
|
-
scan.saaxis_params.scores = scores_dict
|
873
|
-
SAAxisProcess.autofocus(scan)
|
874
|
-
window1.setScan(scan)
|
875
|
-
app.exec_()
|
876
|
-
|
877
|
-
shutil.rmtree(slices_folder)
|
@@ -29,8 +29,8 @@ __date__ = "16/06/2021"
|
|
29
29
|
|
30
30
|
from tomwer.gui.reconstruction.axis import AxisWindow
|
31
31
|
from tomwer.gui.reconstruction.axis.radioaxis import _ManualFramesSelection
|
32
|
-
from tomwer.
|
33
|
-
from tomwer.
|
32
|
+
from tomwer.tests.utils import skip_gui_test
|
33
|
+
from tomwer.tests.utils import UtilsTest
|
34
34
|
from tomwer.core.process.reconstruction.axis.mode import AxisMode
|
35
35
|
from tomwer.core.scan.edfscan import EDFTomoScan
|
36
36
|
from tomwer.synctools.axis import QAxisRP
|
@@ -35,8 +35,8 @@ import pytest
|
|
35
35
|
from silx.gui import qt
|
36
36
|
from tomwer.core import settings
|
37
37
|
from tomwer.gui.reconstruction.lamino.tofu import TofuWindow
|
38
|
-
from tomwer.
|
39
|
-
from tomwer.
|
38
|
+
from tomwer.tests.utils import UtilsTest
|
39
|
+
from tomwer.tests.utils import skip_gui_test
|
40
40
|
|
41
41
|
|
42
42
|
@pytest.mark.skipif(skip_gui_test(), reason="skip gui test")
|
@@ -29,7 +29,7 @@ __date__ = "05/02/2020"
|
|
29
29
|
|
30
30
|
import os
|
31
31
|
from silx.gui import qt
|
32
|
-
from tomwer.
|
32
|
+
from tomwer.tests.utils import skip_gui_test
|
33
33
|
from tomwer.gui.reconstruction.nabu.nabuflow import NabuFlowControl
|
34
34
|
from tomwer.gui.reconstruction.nabu.nabuconfig.preprocessing import (
|
35
35
|
_NabuPreProcessingConfig,
|
@@ -116,6 +116,7 @@ class TestNabuPreProcConfig(TestCaseQt):
|
|
116
116
|
"log_min_clip": 1e-6,
|
117
117
|
"log_max_clip": 10.0,
|
118
118
|
"take_logarithm": True,
|
119
|
+
"normalize_srcurrent": 0,
|
119
120
|
"sino_rings_correction": _RingCorrectionMethod.NONE.value,
|
120
121
|
"sino_rings_options": "sigma=1.0 ; levels=10",
|
121
122
|
"tilt_correction": "",
|
@@ -134,6 +135,7 @@ class TestNabuPreProcConfig(TestCaseQt):
|
|
134
135
|
"log_min_clip": 1e-3,
|
135
136
|
"log_max_clip": 250.0,
|
136
137
|
"take_logarithm": False,
|
138
|
+
"normalize_srcurrent": 1,
|
137
139
|
"sino_rings_correction": _RingCorrectionMethod.MUNCH.value,
|
138
140
|
"sino_rings_options": "sigma=1.4 ; levels=11",
|
139
141
|
"tilt_correction": "1d-correlation",
|
@@ -162,6 +164,10 @@ class TestNabuPhaseConfig(TestCaseQt):
|
|
162
164
|
"padding_type": "edge",
|
163
165
|
"unsharp_coeff": 0,
|
164
166
|
"unsharp_sigma": 0,
|
167
|
+
"beam_shape": "parallel",
|
168
|
+
"ctf_advanced_params": " length_scale=1e-05; lim1=1e-05; lim2=0.2; normalize_by_mean=True",
|
169
|
+
"ctf_geometry": " z1_v=None; z1_h=None; detec_pixel_size=None; magnification=True",
|
170
|
+
"ctf_translations_file": "",
|
165
171
|
}
|
166
172
|
self.assertEqual(self.nabuWidget.getConfiguration(), ini_conf)
|
167
173
|
|
@@ -173,6 +179,10 @@ class TestNabuPhaseConfig(TestCaseQt):
|
|
173
179
|
"padding_type": "zeros",
|
174
180
|
"unsharp_coeff": 3.6,
|
175
181
|
"unsharp_sigma": 2.1,
|
182
|
+
"beam_shape": "cone",
|
183
|
+
"ctf_advanced_params": " length_scale=1e-05; lim1=1e-05; lim2=0.2; normalize_by_mean=True",
|
184
|
+
"ctf_geometry": " z1_v=0.0; z1_h=0.0; detec_pixel_size=None; magnification=True",
|
185
|
+
"ctf_translations_file": "",
|
176
186
|
}
|
177
187
|
self.nabuWidget.setConfiguration(conf)
|
178
188
|
self.nabuWidget.show()
|
@@ -225,6 +235,7 @@ class TestNabuReconstructionConfig(TestCaseQt):
|
|
225
235
|
"positivity_constraint": 1,
|
226
236
|
"translation_movements_file": "",
|
227
237
|
"clip_outer_circle": 0,
|
238
|
+
"centered_axis": 0,
|
228
239
|
}
|
229
240
|
self.assertEqual(self.nabuWidget.getConfiguration(), ini_conf)
|
230
241
|
|
@@ -251,6 +262,7 @@ class TestNabuReconstructionConfig(TestCaseQt):
|
|
251
262
|
"positivity_constraint": 0,
|
252
263
|
"translation_movements_file": "my_file.csv",
|
253
264
|
"clip_outer_circle": 1,
|
265
|
+
"centered_axis": 1,
|
254
266
|
}
|
255
267
|
self.nabuWidget.setConfiguration(ini_conf)
|
256
268
|
self.qapp.processEvents()
|
@@ -268,6 +280,7 @@ class TestNabuReconstructionConfig(TestCaseQt):
|
|
268
280
|
self.assertFalse(subRegionWidget._zSubRegion._maxQLE.isEnabled())
|
269
281
|
self.assertFalse(self.nabuWidget._preconditioningFilter.isChecked())
|
270
282
|
self.assertTrue(self.nabuWidget._clipOuterCircleCB.isChecked())
|
283
|
+
self.assertTrue(self.nabuWidget._centeredAxisCB.isChecked())
|
271
284
|
|
272
285
|
# check the generated configuration
|
273
286
|
self.assertEqual(self.nabuWidget.getConfiguration(), ini_conf)
|
@@ -27,7 +27,7 @@ __license__ = "MIT"
|
|
27
27
|
__date__ = "03/02/2021"
|
28
28
|
|
29
29
|
|
30
|
-
from tomwer.
|
30
|
+
from tomwer.tests.utils import skip_gui_test
|
31
31
|
from tomwer.gui.reconstruction.saaxis.dimensionwidget import DimensionWidget
|
32
32
|
from tomoscan.unitsystem import metricsystem
|
33
33
|
from silx.gui.utils.testutils import TestCaseQt
|
@@ -41,7 +41,6 @@ from tomwer.core.process.reconstruction.scores import ComputedScore
|
|
41
41
|
from tomwer.core.process.reconstruction.scores.params import ScoreMethod
|
42
42
|
from silx.io.url import DataUrl
|
43
43
|
from silx.gui import qt
|
44
|
-
import unittest
|
45
44
|
import pytest
|
46
45
|
import numpy
|
47
46
|
import shutil
|
@@ -203,19 +202,11 @@ class TestSAAxisWindow(TestCaseQt):
|
|
203
202
|
self.assertEqual(configuration[key], res_conf[key])
|
204
203
|
|
205
204
|
def testSetResults(self):
|
206
|
-
"""Test setting results"""
|
205
|
+
"""Test setting results and saving result to a folder"""
|
207
206
|
self._window.setCorScores(self._cor_scores, score_method="standard deviation")
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
TestSAAxisWindow,
|
215
|
-
):
|
216
|
-
test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ui))
|
217
|
-
return test_suite
|
218
|
-
|
219
|
-
|
220
|
-
if __name__ == "__main__":
|
221
|
-
unittest.main(defaultTest="suite")
|
207
|
+
# test saving snapshots
|
208
|
+
with tempfile.TemporaryDirectory() as output_png_imgs:
|
209
|
+
final_dir = os.path.join(output_png_imgs, "test/create/it")
|
210
|
+
self._window.saveReconstructedSlicesTo(final_dir)
|
211
|
+
assert os.path.exists(final_dir)
|
212
|
+
assert len(os.listdir(final_dir)) == len(self._cor_scores)
|
@@ -27,7 +27,7 @@ __license__ = "MIT"
|
|
27
27
|
__date__ = "09/06/2021"
|
28
28
|
|
29
29
|
|
30
|
-
from tomwer.
|
30
|
+
from tomwer.tests.utils import skip_gui_test
|
31
31
|
from silx.gui.utils.testutils import TestCaseQt
|
32
32
|
from tomwer.core.utils.scanutils import MockHDF5
|
33
33
|
from tomwer.gui.reconstruction.sadeltabeta import SADeltaBetaWindow
|
@@ -36,7 +36,6 @@ from tomwer.core.process.reconstruction.scores.params import ScoreMethod
|
|
36
36
|
from tomwer.core.process.reconstruction.scores import ComputedScore
|
37
37
|
from silx.io.url import DataUrl
|
38
38
|
from silx.gui import qt
|
39
|
-
import unittest
|
40
39
|
import pytest
|
41
40
|
import numpy
|
42
41
|
import shutil
|
@@ -132,14 +131,9 @@ class TestSADeltaBetaWindow(TestCaseQt):
|
|
132
131
|
def testSetResults(self):
|
133
132
|
"""Test setting results"""
|
134
133
|
self._window.setDBScores(self._cor_scores, score_method="total variation")
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
return test_suite
|
142
|
-
|
143
|
-
|
144
|
-
if __name__ == "__main__":
|
145
|
-
unittest.main(defaultTest="suite")
|
134
|
+
# test saving snapshots
|
135
|
+
with tempfile.TemporaryDirectory() as output_png_imgs:
|
136
|
+
final_dir = os.path.join(output_png_imgs, "test/create/it")
|
137
|
+
self._window.saveReconstructedSlicesTo(final_dir)
|
138
|
+
assert os.path.exists(final_dir)
|
139
|
+
assert len(os.listdir(final_dir)) == len(self._cor_scores)
|
tomwer/gui/stackplot.py
CHANGED
@@ -44,7 +44,8 @@ import logging
|
|
44
44
|
from tomwer.gui import icons
|
45
45
|
import functools
|
46
46
|
import time
|
47
|
-
from collections import namedtuple
|
47
|
+
from collections import namedtuple
|
48
|
+
from typing import Iterable, Optional
|
48
49
|
|
49
50
|
logger = logging.getLogger(__name__)
|
50
51
|
|
@@ -204,7 +205,7 @@ class _QImageStackPlot(qt.QWidget):
|
|
204
205
|
self._qspinbox.blockSignals(False)
|
205
206
|
|
206
207
|
def createStackImageInstance(self):
|
207
|
-
return _StackImage()
|
208
|
+
return _StackImage(images=None)
|
208
209
|
|
209
210
|
def showImage(self, index):
|
210
211
|
"""
|
@@ -232,25 +233,6 @@ class _QImageStackPlot(qt.QWidget):
|
|
232
233
|
self._qspinbox.blockSignals(False)
|
233
234
|
self._qslider.blockSignals(False)
|
234
235
|
|
235
|
-
def setImage(self, index, data):
|
236
|
-
"""
|
237
|
-
Set the given data as the image for the given index
|
238
|
-
|
239
|
-
:param int index: the index of the image to set
|
240
|
-
:param numpy.ndarray data: the image
|
241
|
-
"""
|
242
|
-
_data = data
|
243
|
-
if data is None:
|
244
|
-
_data = self.IMG_NOT_FOUND
|
245
|
-
self.images[index] = _data
|
246
|
-
|
247
|
-
def isEmpty(self):
|
248
|
-
"""
|
249
|
-
|
250
|
-
:return bool: True if no reconstruction has been set yet
|
251
|
-
"""
|
252
|
-
return self.images.empty()
|
253
|
-
|
254
236
|
def clear(self):
|
255
237
|
self.setImages(None)
|
256
238
|
|
@@ -388,10 +370,6 @@ class _QImageFileStackPlot(_QImageStackPlot):
|
|
388
370
|
self._qslider.valueChanged.connect(self.changeActiveImageFrmQSlider)
|
389
371
|
self._qspinbox.valueChanged.connect(self.changeActiveImageFrmQSpinBox)
|
390
372
|
|
391
|
-
def setLoadingImage(self, sliceNb):
|
392
|
-
"""Set the status of the image to not loaded"""
|
393
|
-
self.setImage(sliceNb, _QImageFileStackPlot.IMG_LOADING)
|
394
|
-
|
395
373
|
def setImages(self, imagesFiles):
|
396
374
|
"""
|
397
375
|
Set the stack of images files
|
@@ -497,7 +475,7 @@ class _QImageFileStackPlot(_QImageStackPlot):
|
|
497
475
|
|
498
476
|
|
499
477
|
class _StackImage(object):
|
500
|
-
def __init__(self, images):
|
478
|
+
def __init__(self, images: Optional[Iterable]):
|
501
479
|
_images = images
|
502
480
|
if _images is None:
|
503
481
|
_images = {}
|
@@ -516,6 +494,11 @@ class _StackImage(object):
|
|
516
494
|
else:
|
517
495
|
return self._images[index]
|
518
496
|
|
497
|
+
def setImages(self, images: Iterable):
|
498
|
+
self.clear()
|
499
|
+
for image in images:
|
500
|
+
self.addImage(image)
|
501
|
+
|
519
502
|
def size(self):
|
520
503
|
return len(self._images)
|
521
504
|
|
@@ -543,9 +526,9 @@ class _StackImageToLoad(_StackImage, qt.QObject):
|
|
543
526
|
"""Signal emitted when the loading mode is changed. Parameter are new mode,
|
544
527
|
old mode"""
|
545
528
|
|
546
|
-
def __init__(self, loadingMode=LAZY_LOADING):
|
529
|
+
def __init__(self, loadingMode=LAZY_LOADING, images: Optional[Iterable] = None):
|
547
530
|
assert loadingMode in (LAZY_LOADING, ASAP_LOADING, ON_SHOW_LOADING)
|
548
|
-
_StackImage.__init__(self, images=
|
531
|
+
_StackImage.__init__(self, images=images)
|
549
532
|
qt.QObject.__init__(self)
|
550
533
|
self._mode = loadingMode
|
551
534
|
self._url_to_index = {}
|
tomwer/gui/test/test_axis_gui.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from tomwer.gui.reconstruction.axis.radioaxis import AxisTabWidget
|
2
2
|
from tomwer.synctools.axis import QAxisRP
|
3
3
|
from silx.gui.utils.testutils import TestCaseQt
|
4
|
-
from tomwer.
|
4
|
+
from tomwer.tests.utils import skip_gui_test
|
5
5
|
import pytest
|
6
6
|
|
7
7
|
|
@@ -13,14 +13,14 @@ class TestGetNabuCorOpts(TestCaseQt):
|
|
13
13
|
"""
|
14
14
|
axis_params = QAxisRP()
|
15
15
|
widget = AxisTabWidget(recons_params=axis_params)
|
16
|
-
assert axis_params.
|
16
|
+
assert axis_params.get_nabu_cor_options_as_str() == "side='all'"
|
17
17
|
widget._calculationWidget._corOpts.setText("low_pass=2")
|
18
18
|
widget._calculationWidget._corOpts.editingFinished.emit()
|
19
|
-
assert axis_params.
|
19
|
+
assert axis_params.get_nabu_cor_options_as_str() == "side='all' ; low_pass=2"
|
20
20
|
widget._calculationWidget._corOpts.setText("low_pass=2 ; high_pass=10")
|
21
21
|
widget._calculationWidget._sideCB.setCurrentText("left")
|
22
22
|
widget._calculationWidget._corOpts.editingFinished.emit()
|
23
23
|
assert (
|
24
|
-
axis_params.
|
24
|
+
axis_params.get_nabu_cor_options_as_str()
|
25
25
|
== "side='left' ; low_pass=2 ; high_pass=10"
|
26
26
|
)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import pytest
|
2
|
+
from tomwer.tests.conftest import qtapp # noqa F401
|
3
|
+
from tomwer.gui.qfolderdialog import QDataDialog
|
4
|
+
|
5
|
+
|
6
|
+
@pytest.mark.parametrize("multi_selection", (True, False))
|
7
|
+
def test_qdata_dialog(
|
8
|
+
qtapp, # noqa F401
|
9
|
+
multi_selection,
|
10
|
+
):
|
11
|
+
dialog = QDataDialog(parent=None, multiSelection=multi_selection)
|
12
|
+
dialog.files_selected()
|
tomwer/gui/utils/inputwidget.py
CHANGED
@@ -249,45 +249,57 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
249
249
|
sigChanged = qt.Signal()
|
250
250
|
"""Signal emit when the output directory of the nx file change"""
|
251
251
|
|
252
|
+
DEFAULT_PROCESSED_DIR = (
|
253
|
+
"{scan_parent_dir_basename}/../PROCESSED_DATA/{scan_dir_name}"
|
254
|
+
)
|
255
|
+
"""Default pattern to find the 'processed' directory"""
|
256
|
+
|
252
257
|
def __init__(self, parent=None):
|
253
258
|
qt.QWidget.__init__(self, parent)
|
254
259
|
self.setLayout(qt.QGridLayout())
|
255
260
|
self.__buttonGroup = qt.QButtonGroup(self)
|
256
261
|
self.__buttonGroup.setExclusive(True)
|
257
262
|
|
258
|
-
|
259
|
-
|
260
|
-
self.
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
)
|
266
|
-
self.
|
267
|
-
self.
|
263
|
+
tooltip = f"""Define the output directory of the nexus (.nx) file. Options are:
|
264
|
+
\n - next to bliss file: create the NXtomos at the same level as the bliss input file
|
265
|
+
\n - 'PROCESSED_DATA' folder: create NXtomos on the default 'PROCESSED_DATA' folder (bliss default folder, nearby the 'raw' folder). Uses {self.DEFAULT_PROCESSED_DIR} pattern
|
266
|
+
\n - user defined folder: users can provide their own folders using keywords for string formatting such as 'scan_dir_name', 'scan_basename' or 'scan_parent_dir_basename'
|
267
|
+
"""
|
268
|
+
|
269
|
+
# output dir is the folder containing the .nx file
|
270
|
+
self._closeToNxRB = qt.QRadioButton("next to bliss file", self)
|
271
|
+
self._closeToNxRB.setToolTip(tooltip)
|
272
|
+
self.layout().addWidget(self._closeToNxRB, 0, 0, 1, 1)
|
273
|
+
self.__buttonGroup.addButton(self._closeToNxRB)
|
274
|
+
# output dir is the default 'reduced'folder
|
275
|
+
self._processedFolderRB = qt.QRadioButton("'PROCESSED_DATA' folder", self)
|
276
|
+
self._processedFolderRB.setToolTip(tooltip)
|
277
|
+
self.layout().addWidget(self._processedFolderRB, 1, 0, 1, 1)
|
278
|
+
self.__buttonGroup.addButton(self._processedFolderRB)
|
268
279
|
# manual
|
269
|
-
self._manualRB = qt.QRadioButton("
|
270
|
-
self._manualRB.setToolTip(
|
271
|
-
self.layout().addWidget(self._manualRB,
|
280
|
+
self._manualRB = qt.QRadioButton("custom output directory", self)
|
281
|
+
self._manualRB.setToolTip(tooltip)
|
282
|
+
self.layout().addWidget(self._manualRB, 2, 0, 1, 1)
|
272
283
|
self._outputFolderQLE = qt.QLineEdit("", self)
|
273
|
-
self.layout().addWidget(self._outputFolderQLE,
|
284
|
+
self.layout().addWidget(self._outputFolderQLE, 2, 1, 1, 1)
|
274
285
|
self._selectButton = qt.QPushButton("", self)
|
275
286
|
style = qt.QApplication.style()
|
276
287
|
icon_opendir = style.standardIcon(qt.QStyle.SP_DirOpenIcon)
|
277
288
|
self._selectButton.setIcon(icon_opendir)
|
278
289
|
self._selectButton.setToolTip("select output directory")
|
279
|
-
self.layout().addWidget(self._selectButton,
|
290
|
+
self.layout().addWidget(self._selectButton, 2, 2, 1, 1)
|
280
291
|
self.__buttonGroup.addButton(self._manualRB)
|
281
292
|
|
282
293
|
# connect signal / slot
|
283
294
|
self._selectButton.released.connect(self._selectOutpuFolder)
|
284
295
|
self.__buttonGroup.buttonReleased.connect(self._updateVisiblity)
|
285
|
-
self.
|
296
|
+
self._closeToNxRB.toggled.connect(self._outputDirChanged)
|
297
|
+
self._processedFolderRB.toggled.connect(self._outputDirChanged)
|
286
298
|
self._manualRB.toggled.connect(self._outputDirChanged)
|
287
299
|
self._outputFolderQLE.editingFinished.connect(self._outputDirChanged)
|
288
300
|
|
289
301
|
# set up
|
290
|
-
self.
|
302
|
+
self._closeToNxRB.setChecked(True)
|
291
303
|
self._updateVisiblity()
|
292
304
|
|
293
305
|
def _updateVisiblity(self, *args, **kwargs):
|
@@ -297,7 +309,7 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
297
309
|
def _outputDirChanged(self):
|
298
310
|
self.sigChanged.emit()
|
299
311
|
|
300
|
-
def _selectOutpuFolder(self):
|
312
|
+
def _selectOutpuFolder(self): # pragma: no cover
|
301
313
|
defaultDirectory = self._outputFolderQLE.text()
|
302
314
|
if os.path.isdir(defaultDirectory):
|
303
315
|
defaultDirectory = get_default_directory()
|
@@ -315,14 +327,23 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
315
327
|
def getOutputFolder(self) -> Union[None, str]:
|
316
328
|
if self._manualRB.isChecked():
|
317
329
|
return self._outputFolderQLE.text()
|
330
|
+
elif self._processedFolderRB.isChecked():
|
331
|
+
return self.DEFAULT_PROCESSED_DIR
|
318
332
|
else:
|
319
333
|
return None
|
320
334
|
|
321
335
|
def setOutputFolder(self, output_folder: Optional[str]):
|
322
336
|
old = self.blockSignals(True)
|
323
337
|
self._manualRB.setChecked(output_folder is not None)
|
324
|
-
if output_folder is
|
325
|
-
self.
|
338
|
+
if output_folder is None:
|
339
|
+
self._closeToNxRB.setChecked()
|
340
|
+
else:
|
341
|
+
is_default_processed_folder = output_folder == self.DEFAULT_PROCESSED_DIR
|
342
|
+
if is_default_processed_folder:
|
343
|
+
self._processedFolderRB.setChecked(True)
|
344
|
+
else:
|
345
|
+
self._outputFolderQLE.setText(output_folder)
|
346
|
+
self._manualRB.setChecked(True)
|
326
347
|
self._updateVisiblity()
|
327
348
|
self.blockSignals(old)
|
328
349
|
|
@@ -359,7 +380,7 @@ class _ConfigFileSelector(qt.QWidget):
|
|
359
380
|
def _clearFilePath(self):
|
360
381
|
self._lineEdit.clear()
|
361
382
|
|
362
|
-
def _selectCFGFile(self):
|
383
|
+
def _selectCFGFile(self): # pragma: no cover
|
363
384
|
dialog = qt.QFileDialog(self)
|
364
385
|
dialog.setFileMode(qt.QFileDialog.ExistingFile)
|
365
386
|
|