tomwer 1.3.0.dev2__py3-none-any.whl → 1.3.0rc10__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/widgets/__init__.py +11 -12
- orangecontrib/tomwer/widgets/control/DataListenerOW.py +6 -6
- orangecontrib/tomwer/widgets/control/DataValidatorOW.py +6 -6
- orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +3 -3
- orangecontrib/tomwer/widgets/control/NXTomomillOW.py +10 -8
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +6 -6
- orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +1 -1
- orangecontrib/tomwer/widgets/icat/RawDataScreenshotCreatorOW.py +98 -98
- orangecontrib/tomwer/widgets/icat/SaveToGalleryAndPublishOW.py +129 -129
- orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +13 -12
- orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +11 -9
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +11 -9
- orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +12 -15
- orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +9 -9
- orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -1
- tomwer/__main__.py +0 -10
- tomwer/app/canvas_launcher/config.py +3 -3
- tomwer/app/canvas_launcher/environ.py +1 -0
- tomwer/app/intensitynormalization.py +12 -11
- tomwer/app/nabuapp.py +0 -11
- tomwer/app/zstitching.py +11 -1
- tomwer/core/process/control/datalistener/datalistener.py +15 -10
- tomwer/core/process/control/nxtomomill.py +1 -1
- tomwer/core/process/control/scantransfer.py +8 -32
- tomwer/core/process/edit/darkflatpatch.py +8 -9
- tomwer/core/process/edit/imagekeyeditor.py +20 -22
- tomwer/core/process/icat/screenshots.py +1 -0
- tomwer/core/process/reconstruction/axis/axis.py +263 -59
- tomwer/core/process/reconstruction/axis/mode.py +161 -50
- tomwer/core/process/reconstruction/axis/params.py +23 -20
- tomwer/core/process/reconstruction/darkref/darkrefs.py +12 -13
- tomwer/core/process/reconstruction/nabu/castvolume.py +3 -3
- tomwer/core/process/reconstruction/nabu/nabucommon.py +43 -19
- tomwer/core/process/reconstruction/nabu/nabuscores.py +34 -7
- tomwer/core/process/reconstruction/nabu/nabuslices.py +81 -26
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +31 -26
- tomwer/core/process/reconstruction/nabu/plane.py +9 -0
- tomwer/core/process/reconstruction/nabu/utils.py +32 -9
- tomwer/core/process/reconstruction/saaxis/saaxis.py +4 -1
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +9 -1
- tomwer/core/process/reconstruction/scores/params.py +3 -3
- tomwer/core/process/reconstruction/test/test_darkref_copy.py +4 -4
- tomwer/core/process/stitching/nabustitcher.py +11 -10
- tomwer/core/process/task.py +33 -27
- tomwer/core/process/test/test_axis.py +7 -6
- tomwer/core/process/test/test_data_transfer.py +3 -3
- tomwer/core/process/test/test_nabu.py +10 -2
- tomwer/core/process/test/test_normalization.py +2 -2
- tomwer/core/scan/blissscan.py +3 -3
- tomwer/core/scan/edfscan.py +9 -9
- tomwer/core/scan/nxtomoscan.py +11 -11
- tomwer/core/scan/scanbase.py +31 -24
- tomwer/core/scan/test/test_future_scan.py +1 -1
- tomwer/core/scan/test/test_h5.py +4 -4
- tomwer/core/scan/test/test_process_registration.py +2 -2
- tomwer/core/scan/test/test_scan.py +1 -75
- tomwer/core/settings.py +3 -3
- tomwer/core/test/test_utils.py +2 -2
- tomwer/core/volume/edfvolume.py +6 -6
- tomwer/core/volume/hdf5volume.py +6 -6
- tomwer/core/volume/jp2kvolume.py +6 -6
- tomwer/core/volume/rawvolume.py +6 -6
- tomwer/core/volume/tiffvolume.py +12 -12
- tomwer/gui/cluster/slurm.py +14 -9
- tomwer/gui/cluster/supervisor.py +12 -0
- tomwer/gui/cluster/test/test_cluster.py +1 -2
- tomwer/gui/cluster/test/test_supervisor.py +1 -1
- tomwer/gui/control/datalist.py +5 -0
- tomwer/gui/control/datawatcher/controlwidget.py +2 -4
- tomwer/gui/control/reducedarkflatselector.py +8 -8
- tomwer/gui/control/test/test_single_tomo_obj.py +1 -1
- tomwer/gui/edit/dkrfpatch.py +4 -4
- tomwer/gui/edit/nxtomowarmer.py +2 -2
- tomwer/gui/edit/test/test_dkrf_patch.py +6 -6
- tomwer/gui/imagefromfile.py +2 -2
- tomwer/gui/qfolderdialog.py +5 -0
- tomwer/gui/reconstruction/axis/CompareImages.py +94 -168
- tomwer/gui/reconstruction/axis/radioaxis.py +58 -182
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -1
- tomwer/gui/reconstruction/nabu/castvolume.py +8 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +54 -21
- tomwer/gui/reconstruction/normalization/intensity.py +3 -25
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +1 -1
- tomwer/gui/reconstruction/saaxis/saaxis.py +1 -11
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +0 -10
- tomwer/gui/reconstruction/scores/scoreplot.py +1 -6
- tomwer/gui/reconstruction/test/test_axis.py +18 -4
- tomwer/gui/reconstruction/test/test_nabu.py +3 -0
- tomwer/gui/stitching/stitching.py +2 -2
- tomwer/gui/stitching/stitching_preview.py +7 -53
- tomwer/gui/stitching/stitching_raw.py +3 -3
- tomwer/gui/utils/inputwidget.py +12 -2
- tomwer/gui/utils/lineselector/lineselector.py +1 -1
- tomwer/gui/visualization/dataviewer.py +47 -17
- tomwer/gui/visualization/sinogramviewer.py +19 -26
- tomwer/gui/visualization/test/test_volumeviewer.py +64 -66
- tomwer/gui/visualization/volumeviewer.py +105 -105
- tomwer/io/utils/h5pyutils.py +7 -3
- tomwer/io/utils/utils.py +3 -3
- tomwer/resources/gui/icons/parameters.svg +1 -1
- tomwer/resources/gui/illustrations/no_rot.svg +1 -1
- tomwer/synctools/stacks/edit/darkflatpatch.py +17 -12
- tomwer/tests/test_scripts.py +0 -3
- tomwer/third_part/WaitingOverlay.py +110 -0
- tomwer/third_part/__init__.py +0 -0
- tomwer/version.py +2 -2
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/METADATA +32 -31
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/RECORD +115 -153
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/WHEEL +1 -1
- orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +0 -197
- orangecontrib/tomwer/widgets/reconstruction/icons/XY_lamino.svg +0 -168
- orangecontrib/tomwer/widgets/reconstruction/icons/XZ_lamino.svg +0 -275
- orangecontrib/tomwer/widgets/reconstruction/icons/YZ_lamino.svg +0 -182
- tomwer/app/lamino.py +0 -143
- tomwer/core/process/reconstruction/lamino/__init__.py +0 -1
- tomwer/core/process/reconstruction/lamino/tofu.py +0 -1000
- tomwer/core/process/test/test_lamino.py +0 -76
- tomwer/core/test/test_lamino.py +0 -92
- tomwer/gui/reconstruction/lamino/__init__.py +0 -31
- tomwer/gui/reconstruction/lamino/tofu/TofuOptionLoader.py +0 -107
- tomwer/gui/reconstruction/lamino/tofu/__init__.py +0 -1
- tomwer/gui/reconstruction/lamino/tofu/misc.py +0 -148
- tomwer/gui/reconstruction/lamino/tofu/projections.py +0 -896
- tomwer/gui/reconstruction/lamino/tofu/settings.py +0 -75
- tomwer/gui/reconstruction/lamino/tofu/tofu.py +0 -432
- tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +0 -567
- tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +0 -757
- tomwer/gui/reconstruction/test/test_lamino.py +0 -194
- tomwer/resources/gui/icons/lamino_parameters.svg +0 -70
- tomwer/resources/gui/illustrations/lamino_angle.png +0 -0
- tomwer/resources/gui/illustrations/lamino_angle.svg +0 -509
- tomwer/resources/gui/illustrations/lamino_beta_angle.png +0 -0
- tomwer/resources/gui/illustrations/lamino_beta_angle.svg +0 -97
- tomwer/resources/gui/illustrations/lamino_theta_angle.png +0 -0
- tomwer/resources/gui/illustrations/lamino_theta_angle.svg +0 -368
- tomwer/resources/gui/illustrations/manual_slice.png +0 -0
- tomwer/resources/gui/illustrations/manual_slice.svg +0 -221
- tomwer/resources/gui/illustrations/psi_angle.png +0 -0
- tomwer/resources/gui/illustrations/psi_angle.svg +0 -479
- tomwer/resources/gui/illustrations/rotation_center.png +0 -0
- tomwer/resources/gui/illustrations/rotation_center.svg +0 -276
- tomwer/resources/gui/illustrations/slice_stack.png +0 -0
- tomwer/resources/gui/illustrations/slice_stack.svg +0 -266
- tomwer/resources/gui/illustrations/xy_slice.png +0 -0
- tomwer/resources/gui/illustrations/xy_slice.svg +0 -269
- tomwer/resources/gui/illustrations/xz_slice.png +0 -0
- tomwer/resources/gui/illustrations/xz_slice.svg +0 -270
- tomwer/resources/gui/illustrations/yz_slice.png +0 -0
- tomwer/resources/gui/illustrations/yz_slice.svg +0 -270
- tomwer/synctools/stacks/reconstruction/lamino.py +0 -233
- /tomwer-1.3.0.dev2-py3.11-nspkg.pth → /tomwer-1.3.0rc10-py3.11-nspkg.pth +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/LICENSE +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/entry_points.txt +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/top_level.txt +0 -0
@@ -1,757 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# /*##########################################################################
|
3
|
-
#
|
4
|
-
# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
|
5
|
-
#
|
6
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
-
# of this software and associated documentation files (the "Software"), to deal
|
8
|
-
# in the Software without restriction, including without limitation the rights
|
9
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
-
# copies of the Software, and to permit persons to whom the Software is
|
11
|
-
# furnished to do so, subject to the following conditions:
|
12
|
-
#
|
13
|
-
# The above copyright notice and this permission notice shall be included in
|
14
|
-
# all copies or substantial portions of the Software.
|
15
|
-
#
|
16
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
-
# THE SOFTWARE.
|
23
|
-
#
|
24
|
-
# ###########################################################################*/
|
25
|
-
|
26
|
-
__authors__ = ["H. Payno"]
|
27
|
-
__license__ = "MIT"
|
28
|
-
__date__ = "01/06/2018"
|
29
|
-
|
30
|
-
|
31
|
-
import logging
|
32
|
-
import os
|
33
|
-
|
34
|
-
from silx.gui import qt
|
35
|
-
|
36
|
-
from tomwer.core.process.reconstruction.lamino.tofu import (
|
37
|
-
LAMINO_ANGLE_TYPE,
|
38
|
-
PSI_ANGLE_TYPE,
|
39
|
-
ROTATION_CENTER_TYPE,
|
40
|
-
SLICE_STACK_TYPE,
|
41
|
-
)
|
42
|
-
from tomwer.core.settings import get_lbsram_path
|
43
|
-
from tomwer.core.utils.char import DELTA_CHAR
|
44
|
-
from tomwer.gui.reconstruction.lamino.tofu import settings
|
45
|
-
from tomwer.gui.utils.illustrations import _IllustrationWidget
|
46
|
-
|
47
|
-
from .misc import PadlockButton, _AngleWidget, _RegionLE
|
48
|
-
from .TofuOptionLoader import _getterSetter, _TofuOptionLoader
|
49
|
-
|
50
|
-
_logger = logging.getLogger(__name__)
|
51
|
-
|
52
|
-
|
53
|
-
class OutputTofuWidget(_TofuOptionLoader, qt.QWidget):
|
54
|
-
"""
|
55
|
-
Main widgets for the tofu reconstruction
|
56
|
-
"""
|
57
|
-
|
58
|
-
def __init__(self, parent):
|
59
|
-
qt.QWidget.__init__(self, parent)
|
60
|
-
self._scan_type = "slice stack"
|
61
|
-
self.__scanID = None
|
62
|
-
self.setLayout(qt.QGridLayout())
|
63
|
-
|
64
|
-
self._controlWidget = qt.QWidget(parent=self)
|
65
|
-
self._controlWidget.setLayout(qt.QVBoxLayout())
|
66
|
-
|
67
|
-
self._volumeAngleGrp = VolumeAnglesWidget(parent=self)
|
68
|
-
self._stepSizeAndRange = StepGroup(parent=self._controlWidget)
|
69
|
-
|
70
|
-
self._planeDisplay = _IllustrationWidget(parent=self)
|
71
|
-
self._planeDisplay.setMinimumSize(qt.QSize(250, 250))
|
72
|
-
self._planeDisplay.setSizePolicy(
|
73
|
-
qt.QSizePolicy.Preferred, qt.QSizePolicy.Preferred
|
74
|
-
)
|
75
|
-
self._controlWidget.layout().setContentsMargins(0, 0, 0, 0)
|
76
|
-
self._controlWidget.layout().addWidget(self._volumeAngleGrp)
|
77
|
-
self._controlWidget.layout().addWidget(self._stepSizeAndRange)
|
78
|
-
self._region = RegionGB(parent=self)
|
79
|
-
self._controlWidget.layout().addWidget(self._region)
|
80
|
-
|
81
|
-
self._outputWidget = _OutputPathWidget(parent=self)
|
82
|
-
self.layout().addWidget(self._outputWidget, 1, 0, 1, 2)
|
83
|
-
|
84
|
-
self.layout().addWidget(self._controlWidget, 0, 0)
|
85
|
-
self.layout().addWidget(self._planeDisplay, 0, 1)
|
86
|
-
|
87
|
-
spacer = qt.QWidget(self)
|
88
|
-
spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
|
89
|
-
self.layout().addWidget(spacer, 2, 0)
|
90
|
-
|
91
|
-
self._controlWidget.setFixedWidth(500)
|
92
|
-
|
93
|
-
# signal/slot connect
|
94
|
-
self._volumeAngleGrp.sigPlaneChanged.connect(self._updateOutput)
|
95
|
-
|
96
|
-
# expose API
|
97
|
-
self.getAngles = self._volumeAngleGrp._angles.get
|
98
|
-
self.getOutput = self._outputWidget.getOutput
|
99
|
-
self.setOutput = self._outputWidget.setOutput
|
100
|
-
self.lockOutput = self._outputWidget.lock
|
101
|
-
self.forceLbsram = self._outputWidget.forceLbsram
|
102
|
-
self.setForceLbsram = self._outputWidget.setForceLbsram
|
103
|
-
self.isOutputFolderLocked = self._outputWidget.isLocked
|
104
|
-
self.removeTiff = self._outputWidget.removeIfExist
|
105
|
-
self.setRemoveTiff = self._outputWidget.setRemoveIfExist
|
106
|
-
self.setVolumeAngleX = self._volumeAngleGrp.setVolumeAngleX
|
107
|
-
self.setVolumeAngleY = self._volumeAngleGrp.setVolumeAngleY
|
108
|
-
self.setVolumeAngleZ = self._volumeAngleGrp.setVolumeAngleZ
|
109
|
-
self.getVolumeAngleX = self._volumeAngleGrp.getVolumeAngleX
|
110
|
-
self.getVolumeAngleY = self._volumeAngleGrp.getVolumeAngleY
|
111
|
-
self.getVolumeAngleZ = self._volumeAngleGrp.getVolumeAngleZ
|
112
|
-
self.setRegionSelType = self._stepSizeAndRange.setRegionSelType
|
113
|
-
self.setRegion = self._stepSizeAndRange.setRegion
|
114
|
-
self.getRegion = self._stepSizeAndRange.getRegion
|
115
|
-
self.dryRun = self._outputWidget.dryRun
|
116
|
-
self.setHighLimit = self._stepSizeAndRange.setHighLimit
|
117
|
-
self.resetHighLimit = self._stepSizeAndRange.resetHighLimit
|
118
|
-
self.getZ = self._stepSizeAndRange.getZ
|
119
|
-
self.setZ = self._stepSizeAndRange.setZ
|
120
|
-
|
121
|
-
options = {
|
122
|
-
"x-region": _getterSetter(
|
123
|
-
getter=self._region.getXRegion, setter=self._region.setXRegionFrmStr
|
124
|
-
),
|
125
|
-
"y-region": _getterSetter(
|
126
|
-
getter=self._region.getYRegion, setter=self._region.setYRegionFrmStr
|
127
|
-
),
|
128
|
-
"volume-angle-x": _getterSetter(
|
129
|
-
getter=self.getVolumeAngleX, setter=self.setVolumeAngleX
|
130
|
-
),
|
131
|
-
"volume-angle-y": _getterSetter(
|
132
|
-
getter=self.getVolumeAngleY, setter=self.setVolumeAngleY
|
133
|
-
),
|
134
|
-
"volume-angle-z": _getterSetter(
|
135
|
-
getter=self.getVolumeAngleZ, setter=self.setVolumeAngleZ
|
136
|
-
),
|
137
|
-
"region": _getterSetter(getter=self.getRegion, setter=self.setRegion),
|
138
|
-
"output": _getterSetter(getter=self.getOutput, setter=self.setOutput),
|
139
|
-
"dry-run": _getterSetter(getter=self.dryRun, setter=self.clearOutput),
|
140
|
-
"z": _getterSetter(getter=self.getZ, setter=self.setZ),
|
141
|
-
"rm-tif": _getterSetter(getter=self.removeTiff, setter=self.setRemoveTiff),
|
142
|
-
}
|
143
|
-
_TofuOptionLoader.__init__(self, options=options)
|
144
|
-
|
145
|
-
def clearOutput(self, *args, **kwargs):
|
146
|
-
self._outputWidget.clear()
|
147
|
-
|
148
|
-
def _setImg(self, plane):
|
149
|
-
assert plane in ("XY", "XZ", "YZ", "manual")
|
150
|
-
self._planeDisplay.setImage(plane + "_lamino")
|
151
|
-
|
152
|
-
def loadFromScan(self, scanID):
|
153
|
-
self.__scanID = scanID
|
154
|
-
self._updateOutput()
|
155
|
-
|
156
|
-
def _updateOutput(self):
|
157
|
-
if self.__scanID is None:
|
158
|
-
return
|
159
|
-
try:
|
160
|
-
if self.isOutputFolderLocked() is False:
|
161
|
-
self.setOutput(os.path.join(self.__scanID, self._getNameExtension()))
|
162
|
-
except Exception as error:
|
163
|
-
_logger.error(error)
|
164
|
-
|
165
|
-
def setPlane(self, plane):
|
166
|
-
self._volumeAngleGrp._grpPlane.setPlane(plane=plane)
|
167
|
-
|
168
|
-
def _getNameExtension(self):
|
169
|
-
"""Return the default name extension according to the scan type"""
|
170
|
-
if self._scan_type == SLICE_STACK_TYPE:
|
171
|
-
if self._volumeAngleGrp._grpPlane.getPlane() == "XY":
|
172
|
-
return "xySlice"
|
173
|
-
elif self._volumeAngleGrp._grpPlane.getPlane() == "XZ":
|
174
|
-
return "xzSlice"
|
175
|
-
elif self._volumeAngleGrp._grpPlane.getPlane() == "YZ":
|
176
|
-
return "yzSlice"
|
177
|
-
elif self._volumeAngleGrp._grpPlane.getPlane() == "manual":
|
178
|
-
return "Slice"
|
179
|
-
elif self._scan_type == ROTATION_CENTER_TYPE:
|
180
|
-
return "xCenter"
|
181
|
-
elif self._scan_type == LAMINO_ANGLE_TYPE:
|
182
|
-
return "ctAngle"
|
183
|
-
elif self._scan_type in (PSI_ANGLE_TYPE, "psi angle"):
|
184
|
-
return "rotC"
|
185
|
-
else:
|
186
|
-
return "Slice"
|
187
|
-
|
188
|
-
def _setScanType(self, scan_type):
|
189
|
-
self._scan_type = scan_type
|
190
|
-
illustration = scan_type
|
191
|
-
if illustration == "slice stack":
|
192
|
-
if self._volumeAngleGrp._grpPlane.getPlane() == "XY":
|
193
|
-
illustration = "xy slice"
|
194
|
-
elif self._volumeAngleGrp._grpPlane.getPlane() == "XZ":
|
195
|
-
illustration = "xz slice"
|
196
|
-
elif self._volumeAngleGrp._grpPlane.getPlane() == "YZ":
|
197
|
-
illustration = "yz slice"
|
198
|
-
elif self._volumeAngleGrp._grpPlane.getPlane() == "manual":
|
199
|
-
illustration = "manual slice"
|
200
|
-
self._planeDisplay.setImage(illustration)
|
201
|
-
|
202
|
-
self._updateOutput()
|
203
|
-
|
204
|
-
|
205
|
-
class PlaneGroup(qt.QGroupBox):
|
206
|
-
sigPlaneChanged = qt.Signal(str)
|
207
|
-
"""Signal emitted when the plane selection changed"""
|
208
|
-
|
209
|
-
def __init__(self, parent):
|
210
|
-
qt.QGroupBox.__init__(self, parent=parent, title="Plane selection")
|
211
|
-
|
212
|
-
self.setLayout(qt.QVBoxLayout())
|
213
|
-
self._XYPlaneRB = qt.QRadioButton("XY", parent=self)
|
214
|
-
self.layout().addWidget(self._XYPlaneRB)
|
215
|
-
self._YZPlaneRB = qt.QRadioButton("YZ", parent=self)
|
216
|
-
self.layout().addWidget(self._YZPlaneRB)
|
217
|
-
self._XZPlaneRB = qt.QRadioButton("XZ", parent=self)
|
218
|
-
self.layout().addWidget(self._XZPlaneRB)
|
219
|
-
self._autoPlaneRB = qt.QRadioButton("manual", parent=self)
|
220
|
-
self.layout().addWidget(self._autoPlaneRB)
|
221
|
-
|
222
|
-
self._rBtns = (
|
223
|
-
self._XYPlaneRB,
|
224
|
-
self._XZPlaneRB,
|
225
|
-
self._YZPlaneRB,
|
226
|
-
self._autoPlaneRB,
|
227
|
-
)
|
228
|
-
self._XYPlaneRB.setChecked(True)
|
229
|
-
|
230
|
-
for btn in self._rBtns:
|
231
|
-
btn.toggled.connect(self.__planeChangedCllbck)
|
232
|
-
|
233
|
-
self.setSizePolicy(qt.QSizePolicy.Preferred, qt.QSizePolicy.Preferred)
|
234
|
-
|
235
|
-
def getPlane(self):
|
236
|
-
if self._XYPlaneRB.isChecked():
|
237
|
-
return "XY"
|
238
|
-
if self._YZPlaneRB.isChecked():
|
239
|
-
return "YZ"
|
240
|
-
if self._XZPlaneRB.isChecked():
|
241
|
-
return "XZ"
|
242
|
-
if self._autoPlaneRB.isChecked():
|
243
|
-
return "manual"
|
244
|
-
|
245
|
-
def setPlane(self, plane):
|
246
|
-
assert plane in ("XY", "XZ", "YZ", "manual")
|
247
|
-
for w in self._rBtns:
|
248
|
-
w.blockSignals(True)
|
249
|
-
if plane == "XY":
|
250
|
-
self._XYPlaneRB.setChecked(True)
|
251
|
-
elif plane == "XZ":
|
252
|
-
self._XZPlaneRB.setChecked(True)
|
253
|
-
elif plane == "YZ":
|
254
|
-
self._YZPlaneRB.setChecked(True)
|
255
|
-
else:
|
256
|
-
self._autoPlaneRB.setChecked(True)
|
257
|
-
self.sigPlaneChanged.emit(plane)
|
258
|
-
for w in self._rBtns:
|
259
|
-
w.blockSignals(False)
|
260
|
-
|
261
|
-
def __planeChangedCllbck(self):
|
262
|
-
self.sigPlaneChanged.emit(self.getPlane())
|
263
|
-
|
264
|
-
def setManualEdition(self):
|
265
|
-
self._autoPlaneRB.setChecked(True)
|
266
|
-
|
267
|
-
|
268
|
-
class VolumeAnglesWidget(qt.QWidget):
|
269
|
-
def __init__(self, parent):
|
270
|
-
qt.QWidget.__init__(self, parent)
|
271
|
-
self.setLayout(qt.QHBoxLayout())
|
272
|
-
self._grpPlane = PlaneGroup(parent=self)
|
273
|
-
self.layout().addWidget(self._grpPlane)
|
274
|
-
self._angles = _AnglesWidget(parent=self)
|
275
|
-
self.layout().addWidget(self._angles)
|
276
|
-
|
277
|
-
# API exposed
|
278
|
-
self.sigPlaneChanged = self._grpPlane.sigPlaneChanged
|
279
|
-
self.sigAnglesEdited = self._angles.sigAnglesEdited
|
280
|
-
|
281
|
-
self.sigAnglesEdited.connect(self._grpPlane.setManualEdition)
|
282
|
-
self.sigPlaneChanged.connect(self._resetAngleFor)
|
283
|
-
|
284
|
-
self.setAngles = self._angles.set
|
285
|
-
self.getAngles = self._angles.get
|
286
|
-
self.setVolumeAngleX = self._angles.setVolumeAngleX
|
287
|
-
self.setVolumeAngleY = self._angles.setVolumeAngleY
|
288
|
-
self.setVolumeAngleZ = self._angles.setVolumeAngleZ
|
289
|
-
self.getVolumeAngleX = self._angles.getVolumeAngleX
|
290
|
-
self.getVolumeAngleY = self._angles.getVolumeAngleY
|
291
|
-
self.getVolumeAngleZ = self._angles.getVolumeAngleZ
|
292
|
-
|
293
|
-
def _resetAngleFor(self, plane):
|
294
|
-
assert plane in ("XY", "XZ", "YZ", "manual")
|
295
|
-
if plane == "manual":
|
296
|
-
return
|
297
|
-
|
298
|
-
if plane == "XY":
|
299
|
-
self._angles.set(0, 0, 0)
|
300
|
-
if plane == "XZ":
|
301
|
-
self._angles.set(90, 0, 0)
|
302
|
-
if plane == "YZ":
|
303
|
-
self._angles.set(0, 90, 0)
|
304
|
-
|
305
|
-
|
306
|
-
class _AnglesWidget(qt.QWidget):
|
307
|
-
sigAnglesEdited = qt.Signal()
|
308
|
-
"""Signal emitted when an angle is edited"""
|
309
|
-
|
310
|
-
def __init__(self, parent):
|
311
|
-
qt.QWidget.__init__(self, parent)
|
312
|
-
self.setLayout(qt.QVBoxLayout())
|
313
|
-
self.layout().setContentsMargins(0, 0, 0, 0)
|
314
|
-
self._spacerTop = qt.QWidget(parent=self)
|
315
|
-
self._spacerTop.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
|
316
|
-
self.layout().addWidget(self._spacerTop)
|
317
|
-
|
318
|
-
self._volAngleX = _AngleWidget(parent=self, name="volume angle x")
|
319
|
-
self.layout().addWidget(self._volAngleX)
|
320
|
-
self._volAngleY = _AngleWidget(parent=self, name="volume angle y")
|
321
|
-
self.layout().addWidget(self._volAngleY)
|
322
|
-
self._volAngleZ = _AngleWidget(parent=self, name="volume angle z")
|
323
|
-
self.layout().addWidget(self._volAngleZ)
|
324
|
-
self._spacerBot = qt.QWidget(parent=self)
|
325
|
-
self._spacerBot.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
|
326
|
-
self.layout().addWidget(self._spacerBot)
|
327
|
-
|
328
|
-
self._volAngleX.sigEdited.connect(self.sigAnglesEdited)
|
329
|
-
self._volAngleY.sigEdited.connect(self.sigAnglesEdited)
|
330
|
-
self._volAngleZ.sigEdited.connect(self.sigAnglesEdited)
|
331
|
-
|
332
|
-
# aliases
|
333
|
-
self.setVolumeAngleX = self._volAngleX.setAngle
|
334
|
-
self.setVolumeAngleY = self._volAngleY.setAngle
|
335
|
-
self.setVolumeAngleZ = self._volAngleZ.setAngle
|
336
|
-
self.getVolumeAngleX = self._volAngleX.getAngle
|
337
|
-
self.getVolumeAngleY = self._volAngleY.getAngle
|
338
|
-
self.getVolumeAngleZ = self._volAngleZ.getAngle
|
339
|
-
|
340
|
-
def set(self, xAngle, yAngle, zAngle):
|
341
|
-
self.blockSignals(True)
|
342
|
-
self.setVolumeAngleX(xAngle)
|
343
|
-
self.setVolumeAngleY(yAngle)
|
344
|
-
self.setVolumeAngleZ(zAngle)
|
345
|
-
self.blockSignals(False)
|
346
|
-
|
347
|
-
def get(self):
|
348
|
-
"""
|
349
|
-
|
350
|
-
:return: tuple of (anglex, angley, anglez)
|
351
|
-
"""
|
352
|
-
return (
|
353
|
-
self._volAngleX.getAngle(),
|
354
|
-
self._volAngleY.getAngle(),
|
355
|
-
self._volAngleZ.getAngle(),
|
356
|
-
)
|
357
|
-
|
358
|
-
|
359
|
-
class StepGroup(qt.QGroupBox):
|
360
|
-
sigSelectionChanged = qt.Signal()
|
361
|
-
"""Signal emitted when the selection changed"""
|
362
|
-
|
363
|
-
_NB_SLICE_NAME = "number of slices"
|
364
|
-
_RANGE_NAME = "range"
|
365
|
-
|
366
|
-
_TITLE = "Cut selection"
|
367
|
-
|
368
|
-
def __init__(self, parent):
|
369
|
-
qt.QGroupBox.__init__(self, parent=parent, title=StepGroup._TITLE)
|
370
|
-
self._xcenter = 0.0
|
371
|
-
self.__mediumLimit = settings._N_SLICE_LIMITS_MEDIUM
|
372
|
-
self.__highLimit = settings._N_SLICE_LIMITS_HIGH
|
373
|
-
|
374
|
-
self._defaultStyleSheet = ""
|
375
|
-
self._mediumLimitStyleSheet = (
|
376
|
-
"QLineEdit {" + self._convertToStyleSheetColor(settings._COLOR_MEDIUM) + "}"
|
377
|
-
)
|
378
|
-
self._highLimitStyleSheet = (
|
379
|
-
"QLineEdit {" + self._convertToStyleSheetColor(settings._COLOR_HIGH) + "}"
|
380
|
-
)
|
381
|
-
|
382
|
-
self.setLayout(qt.QGridLayout())
|
383
|
-
|
384
|
-
# z
|
385
|
-
self._z_label = qt.QLabel("z", parent=self)
|
386
|
-
self.layout().addWidget(self._z_label, 0, 0)
|
387
|
-
self._zSB = qt.QSpinBox(parent=self)
|
388
|
-
self._zSB.setMinimum(-99999)
|
389
|
-
self._zSB.setValue(0)
|
390
|
-
self.layout().addWidget(self._zSB, 0, 1)
|
391
|
-
|
392
|
-
# step size
|
393
|
-
self._stepLabel = qt.QLabel("", parent=self)
|
394
|
-
self.layout().addWidget(self._stepLabel, 1, 0)
|
395
|
-
|
396
|
-
self._stepSize = qt.QLineEdit("1.0", parent=self)
|
397
|
-
validator = qt.QDoubleValidator(parent=self._stepSize)
|
398
|
-
validator.setBottom(0)
|
399
|
-
self._stepSize.setValidator(validator)
|
400
|
-
self.layout().addWidget(self._stepSize, 1, 1, 1, 6)
|
401
|
-
|
402
|
-
style = qt.QApplication.style()
|
403
|
-
icon = style.standardIcon(qt.QStyle.SP_MessageBoxWarning)
|
404
|
-
self._warningLabel = qt.QLabel("", parent=self)
|
405
|
-
self._warningLabel.setPixmap(icon.pixmap(30, state=qt.QIcon.On))
|
406
|
-
self._warningLabel.setVisible(False)
|
407
|
-
self._warningLabel.setToolTip(
|
408
|
-
"Number of slice to reconstruct seems to high, might fail"
|
409
|
-
)
|
410
|
-
|
411
|
-
self.layout().addWidget(self._warningLabel, 1, 7, 1, 1)
|
412
|
-
|
413
|
-
# selection mode
|
414
|
-
self.layout().addWidget(qt.QLabel("selection mode:"), 2, 0)
|
415
|
-
self._selModeTooltips = {
|
416
|
-
self._NB_SLICE_NAME: "Will pick n slices from centered in the center, "
|
417
|
-
"spaced of step size",
|
418
|
-
self._RANGE_NAME: "Will pick slices from a range, each spaced of "
|
419
|
-
"step size",
|
420
|
-
}
|
421
|
-
self._selectionMode = qt.QComboBox(parent=self)
|
422
|
-
self._selectionMode.addItem(self._NB_SLICE_NAME)
|
423
|
-
idx = self._selectionMode.findText(self._NB_SLICE_NAME)
|
424
|
-
self._selectionMode.setItemData(
|
425
|
-
idx, self._selModeTooltips[self._NB_SLICE_NAME], qt.Qt.ToolTipRole
|
426
|
-
)
|
427
|
-
self._selectionMode.addItem(self._RANGE_NAME)
|
428
|
-
idx = self._selectionMode.findText(self._RANGE_NAME)
|
429
|
-
self._selectionMode.setItemData(
|
430
|
-
idx, self._selModeTooltips[self._RANGE_NAME], qt.Qt.ToolTipRole
|
431
|
-
)
|
432
|
-
self.layout().addWidget(self._selectionMode, 2, 1)
|
433
|
-
|
434
|
-
self._nCutLE = qt.QLineEdit(str(-settings.SLICE_STACK_STEP_SIZE), self)
|
435
|
-
validator = qt.QIntValidator(parent=self._nCutLE)
|
436
|
-
validator.setBottom(1)
|
437
|
-
self._nCutLE.setValidator(validator)
|
438
|
-
self.layout().addWidget(self._nCutLE, 2, 2)
|
439
|
-
|
440
|
-
self._fromLabel = qt.QLabel("from:", self)
|
441
|
-
self.layout().addWidget(self._fromLabel, 2, 3)
|
442
|
-
self._fromLE = qt.QLineEdit(str(-settings.SLICE_STACK_RANGE_HS), self)
|
443
|
-
validator = qt.QDoubleValidator(parent=self._fromLE)
|
444
|
-
self._fromLE.setValidator(validator)
|
445
|
-
self.layout().addWidget(self._fromLE, 2, 4)
|
446
|
-
self._toLabel = qt.QLabel("to:", self)
|
447
|
-
self.layout().addWidget(self._toLabel, 2, 5)
|
448
|
-
self._toLE = qt.QLineEdit(str(settings.SLICE_STACK_RANGE_HS), self)
|
449
|
-
validator = qt.QDoubleValidator(parent=self._toLE)
|
450
|
-
self._toLE.setValidator(validator)
|
451
|
-
self.layout().addWidget(self._toLE, 2, 6)
|
452
|
-
|
453
|
-
self.setRegionSelType(self._RANGE_NAME)
|
454
|
-
self._selectionMode.currentIndexChanged[str].connect(self.setRegionSelType)
|
455
|
-
self._setStepSizeType("(pixel)")
|
456
|
-
|
457
|
-
# connect signals / SLOT
|
458
|
-
for widget in (self._nCutLE, self._stepSize, self._toLE, self._fromLE):
|
459
|
-
widget.textChanged.connect(self._updateLimitsColor)
|
460
|
-
|
461
|
-
@staticmethod
|
462
|
-
def _convertToStyleSheetColor(color):
|
463
|
-
assert type(color) is tuple
|
464
|
-
_color = []
|
465
|
-
[_color.append(str(c)) for c in color]
|
466
|
-
return "color: rgb(" + ",".join(_color) + ")"
|
467
|
-
|
468
|
-
def _setStepSizeType(self, _type):
|
469
|
-
assert type(_type) is str
|
470
|
-
self._stepLabel.setText(" ".join(("Step size -", DELTA_CHAR, _type)))
|
471
|
-
|
472
|
-
def setRegionSelType(self, selType):
|
473
|
-
"""
|
474
|
-
|
475
|
-
:param str selType: should be in ('range', 'number of cut')
|
476
|
-
"""
|
477
|
-
assert selType in (self._RANGE_NAME, self._NB_SLICE_NAME)
|
478
|
-
index = self._selectionMode.findText(selType)
|
479
|
-
assert index >= 0
|
480
|
-
self._selectionMode.blockSignals(True)
|
481
|
-
self._selectionMode.setCurrentIndex(index)
|
482
|
-
self._selectionMode.setToolTip(self._selModeTooltips[selType])
|
483
|
-
for w in (self._fromLE, self._toLE, self._toLabel, self._fromLabel):
|
484
|
-
w.setVisible(selType == self._RANGE_NAME)
|
485
|
-
self._nCutLE.setVisible(selType == self._NB_SLICE_NAME)
|
486
|
-
self._selectionMode.blockSignals(False)
|
487
|
-
self.sigSelectionChanged.emit()
|
488
|
-
|
489
|
-
def getSelectionType(self):
|
490
|
-
"""Return active selected mode ('range' or 'number of cut')"""
|
491
|
-
return self._selectionMode.currentText()
|
492
|
-
|
493
|
-
def getStepSize(self):
|
494
|
-
"""Return step size in fofu ref (meter)"""
|
495
|
-
return float(self._stepSize.text())
|
496
|
-
|
497
|
-
def getNCut(self):
|
498
|
-
if self.getSelectionType() != self._NB_SLICE_NAME:
|
499
|
-
return None
|
500
|
-
else:
|
501
|
-
return int(self._nCutLE.text())
|
502
|
-
|
503
|
-
def setNCut(self, ncut):
|
504
|
-
self._nCutLE.setText(str(ncut))
|
505
|
-
|
506
|
-
def getRegion(self):
|
507
|
-
if self.getSelectionType() == self._NB_SLICE_NAME:
|
508
|
-
start_from = self._xcenter
|
509
|
-
if self._zSB.isVisible() is True:
|
510
|
-
start_from = self.getZ() or 0.0
|
511
|
-
nbCut = self.getNCut()
|
512
|
-
if nbCut is None:
|
513
|
-
raise ValueError("couldn't find nb cut")
|
514
|
-
else:
|
515
|
-
_from = (
|
516
|
-
-nbCut / 2 * self.getStepSize() # pylint: disable=E1130
|
517
|
-
+ start_from
|
518
|
-
)
|
519
|
-
_to = nbCut / 2 * self.getStepSize() + start_from
|
520
|
-
return _from, _to, self.getStepSize()
|
521
|
-
else:
|
522
|
-
start_from = 0.0
|
523
|
-
if self._zSB.isVisible() is True:
|
524
|
-
start_from = self.getZ() or 0.0
|
525
|
-
# question: are from, to always integers ?
|
526
|
-
return (
|
527
|
-
float(self._fromLE.text()) + start_from,
|
528
|
-
float(self._toLE.text()) + start_from,
|
529
|
-
float(self.getStepSize()),
|
530
|
-
)
|
531
|
-
|
532
|
-
def setRegion(self, region):
|
533
|
-
if type(region) is str:
|
534
|
-
try:
|
535
|
-
_from, _to, step_size = region.split(",")
|
536
|
-
except Exception:
|
537
|
-
_logger.warning(
|
538
|
-
"Fail to setRegion range. given string "
|
539
|
-
"does not fir the standard (from, to, stepSize)"
|
540
|
-
)
|
541
|
-
return
|
542
|
-
else:
|
543
|
-
assert type(region) is tuple
|
544
|
-
_from, _to, step_size = region
|
545
|
-
_from, _to, step_size = str(_from), str(_to), str(step_size)
|
546
|
-
|
547
|
-
self._fromLE.setText(_from)
|
548
|
-
self._toLE.setText(_to)
|
549
|
-
self._stepSize.setText(step_size)
|
550
|
-
|
551
|
-
def _updateLimitsColor(self, *argv, **kwargs):
|
552
|
-
warning = False
|
553
|
-
if self._isUpperHightLimit() is True:
|
554
|
-
styleSheet = self._highLimitStyleSheet
|
555
|
-
warning = True
|
556
|
-
elif self._isUpperMediumLimit() is True:
|
557
|
-
styleSheet = self._mediumLimitStyleSheet
|
558
|
-
warning = True
|
559
|
-
else:
|
560
|
-
styleSheet = self._defaultStyleSheet
|
561
|
-
|
562
|
-
for widget in (self._fromLE, self._toLE, self._nCutLE, self._stepSize):
|
563
|
-
widget.blockSignals(True)
|
564
|
-
|
565
|
-
self.setStyleSheet(styleSheet)
|
566
|
-
|
567
|
-
for widget in (self._fromLE, self._toLE, self._nCutLE, self._stepSize):
|
568
|
-
widget.blockSignals(False)
|
569
|
-
|
570
|
-
self._warningLabel.setVisible(warning)
|
571
|
-
|
572
|
-
def _isUpperMediumLimit(self):
|
573
|
-
return self._getNSlices() > self.__mediumLimit
|
574
|
-
|
575
|
-
def _isUpperHightLimit(self):
|
576
|
-
return self._getNSlices() > self.__highLimit
|
577
|
-
|
578
|
-
def _getNSlices(self):
|
579
|
-
"""
|
580
|
-
|
581
|
-
:return: number of slice to be reconstructed
|
582
|
-
:rtype: int
|
583
|
-
"""
|
584
|
-
if self.getSelectionType() == self._NB_SLICE_NAME:
|
585
|
-
return self.getNCut()
|
586
|
-
else:
|
587
|
-
# as this cast is made during edition, several value can fail on the
|
588
|
-
# float conversion or division
|
589
|
-
try:
|
590
|
-
_from = float(self._fromLE.text())
|
591
|
-
_to = float(self._toLE.text())
|
592
|
-
_step = float(self.getStepSize())
|
593
|
-
return int((_to - _from) / _step)
|
594
|
-
except Exception:
|
595
|
-
return 1.0
|
596
|
-
|
597
|
-
def setHighLimit(self, val):
|
598
|
-
if val == self.__highLimit:
|
599
|
-
return
|
600
|
-
if val is None:
|
601
|
-
self.resetHighLimit()
|
602
|
-
return
|
603
|
-
if val <= 0.0:
|
604
|
-
_logger.error("incoherent height limit: %s" % val)
|
605
|
-
return
|
606
|
-
|
607
|
-
self.__highLimit = val
|
608
|
-
self._updateLimitsColor()
|
609
|
-
|
610
|
-
def resetHighLimit(self):
|
611
|
-
self.__highLimit = settings._N_SLICE_LIMITS_HIGH
|
612
|
-
self._updateLimitsColor()
|
613
|
-
|
614
|
-
def getZ(self):
|
615
|
-
if self._zSB.isVisible():
|
616
|
-
return self._zSB.value()
|
617
|
-
else:
|
618
|
-
return None
|
619
|
-
|
620
|
-
def setZ(self, value):
|
621
|
-
if value is None:
|
622
|
-
return
|
623
|
-
return self._zSB.setValue(int(value))
|
624
|
-
|
625
|
-
def _setXCenter(self, xcenter):
|
626
|
-
self._xcenter = xcenter
|
627
|
-
|
628
|
-
|
629
|
-
class RegionGB(qt.QGroupBox):
|
630
|
-
def __init__(self, parent):
|
631
|
-
super().__init__("ROI", parent=parent)
|
632
|
-
self.setLayout(qt.QVBoxLayout())
|
633
|
-
self._xRegion = _RegionLE(name="x ROI", parent=self)
|
634
|
-
self.layout().addWidget(self._xRegion)
|
635
|
-
self._yRegion = _RegionLE(name="y ROI", parent=self)
|
636
|
-
self.layout().addWidget(self._yRegion)
|
637
|
-
|
638
|
-
# expose API
|
639
|
-
self.getXRegion = self._xRegion.getRegion
|
640
|
-
self.getYRegion = self._yRegion.getRegion
|
641
|
-
self.setXRegion = self._xRegion.setRegion
|
642
|
-
self.setYRegion = self._yRegion.setRegion
|
643
|
-
self.setXRegionFrmStr = self._xRegion.setRegionFromStr
|
644
|
-
self.setYRegionFrmStr = self._yRegion.setRegionFromStr
|
645
|
-
|
646
|
-
|
647
|
-
class _OutputPathWidget(qt.QGroupBox):
|
648
|
-
class _OptionsWidget(qt.QWidget):
|
649
|
-
def __init__(self, parent):
|
650
|
-
super().__init__(parent)
|
651
|
-
self.setLayout(qt.QHBoxLayout())
|
652
|
-
self.layout().setContentsMargins(0, 0, 0, 0)
|
653
|
-
|
654
|
-
self.forceLbsram = qt.QCheckBox("force lbsram", parent=self)
|
655
|
-
self.forceLbsram.setToolTip("Make sure reconstruction is saved in lbsram")
|
656
|
-
self.layout().addWidget(self.forceLbsram)
|
657
|
-
self.forceLbsram.setVisible(os.path.exists(get_lbsram_path()))
|
658
|
-
|
659
|
-
self.removeExisting = qt.QCheckBox('rm "*.tif"', parent=self)
|
660
|
-
self.removeExisting.setToolTip("Remove existing files if any")
|
661
|
-
self.layout().addWidget(self.removeExisting)
|
662
|
-
spacer = qt.QWidget(self)
|
663
|
-
spacer.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Minimum)
|
664
|
-
self.layout().addWidget(spacer)
|
665
|
-
|
666
|
-
def __init__(self, parent):
|
667
|
-
super().__init__("output folder", parent)
|
668
|
-
self.setLayout(qt.QVBoxLayout())
|
669
|
-
self.layout().setContentsMargins(4, 4, 4, 4)
|
670
|
-
|
671
|
-
self._checkboxWidget = _OutputPathWidget._OptionsWidget(parent=self)
|
672
|
-
self.layout().addWidget(self._checkboxWidget)
|
673
|
-
|
674
|
-
self._qteFolderSelected = qt.QLineEdit("", parent=self)
|
675
|
-
style = qt.QApplication.style()
|
676
|
-
icon = style.standardIcon(qt.QStyle.SP_DialogOpenButton)
|
677
|
-
self._qtbSelectFolder = qt.QPushButton(icon, "", parent=self)
|
678
|
-
self._qteFolderSelected.setToolTip(
|
679
|
-
"If not output folder is given, then" ' this will generate a "dry run"'
|
680
|
-
)
|
681
|
-
|
682
|
-
self._lockButton = PadlockButton(parent=self)
|
683
|
-
self._lockButton.toggled.connect(self._dealWithLbsramOptAndLocker)
|
684
|
-
|
685
|
-
leWidget = qt.QWidget(parent=self)
|
686
|
-
leWidget.setLayout(qt.QHBoxLayout())
|
687
|
-
leWidget.layout().setContentsMargins(0, 0, 0, 0)
|
688
|
-
leWidget.layout().addWidget(self._qteFolderSelected)
|
689
|
-
leWidget.layout().addWidget(self._qtbSelectFolder)
|
690
|
-
leWidget.layout().addWidget(self._lockButton)
|
691
|
-
self.layout().addWidget(leWidget)
|
692
|
-
|
693
|
-
# connect signals/SLOT
|
694
|
-
self._checkboxWidget.forceLbsram.toggled.connect(self._updateLbsramStatus)
|
695
|
-
self._qtbSelectFolder.clicked.connect(self._setFolderPathFrmDiag)
|
696
|
-
self._qteFolderSelected.editingFinished.connect(self._checkUpdateforLbsram)
|
697
|
-
|
698
|
-
# add some speaking API
|
699
|
-
self.clear = self._qteFolderSelected.clear
|
700
|
-
self.isLocked = self._lockButton.isLocked
|
701
|
-
self.forceLbsram = self._checkboxWidget.forceLbsram.isChecked
|
702
|
-
self.setForceLbsram = self._checkboxWidget.forceLbsram.setChecked
|
703
|
-
self.removeIfExist = self._checkboxWidget.removeExisting.isChecked
|
704
|
-
self.setRemoveIfExist = self._checkboxWidget.removeExisting.setChecked
|
705
|
-
|
706
|
-
def setOutput(self, text):
|
707
|
-
if self.forceLbsram() is True and text.startswith(get_lbsram_path()) is False:
|
708
|
-
text = os.path.join(get_lbsram_path(), text.lstrip(os.sep))
|
709
|
-
self._qteFolderSelected.setText(text)
|
710
|
-
|
711
|
-
def lock(self, lock=True):
|
712
|
-
self._lockButton.setChecked(lock)
|
713
|
-
|
714
|
-
def _setFolderPathFrmDiag(self): # pragma: no cover
|
715
|
-
dialog = qt.QFileDialog(self)
|
716
|
-
dialog.setFileMode(qt.QFileDialog.DirectoryOnly)
|
717
|
-
|
718
|
-
if not dialog.exec_() or (len(dialog.selectedFiles()) < 1):
|
719
|
-
dialog.close()
|
720
|
-
return
|
721
|
-
self._qteFolderSelected.setText(dialog.selectedFiles()[0])
|
722
|
-
|
723
|
-
def dryRun(self):
|
724
|
-
"""Should we execute a dry-run and avoid storing reconstruction"""
|
725
|
-
return self.getOutput() is None
|
726
|
-
|
727
|
-
def getOutput(self):
|
728
|
-
"""Return output folder whre the reconstruction should be saved"""
|
729
|
-
if self._qteFolderSelected.text() == "":
|
730
|
-
return None
|
731
|
-
else:
|
732
|
-
return self.__getOutputWithLbsramExtension()
|
733
|
-
|
734
|
-
def _dealWithLbsramOptAndLocker(self, toggle):
|
735
|
-
self._checkboxWidget.forceLbsram.setDisabled(toggle)
|
736
|
-
if toggle:
|
737
|
-
self._checkboxWidget.forceLbsram.setChecked(False)
|
738
|
-
|
739
|
-
def _updateLbsramStatus(self, toggle):
|
740
|
-
if toggle is True:
|
741
|
-
self._qteFolderSelected.setText(self.__getOutputWithLbsramExtension())
|
742
|
-
|
743
|
-
def __getOutputWithLbsramExtension(self):
|
744
|
-
_output = self._qteFolderSelected.text()
|
745
|
-
if (
|
746
|
-
self.forceLbsram() is True
|
747
|
-
and _output.startswith(get_lbsram_path()) is False
|
748
|
-
):
|
749
|
-
_output = os.path.join(get_lbsram_path(), _output.lstrip(os.sep))
|
750
|
-
return _output
|
751
|
-
|
752
|
-
def _checkUpdateforLbsram(self):
|
753
|
-
"""Check if the line edit value has to be changed if force lbsram is
|
754
|
-
active and the line does not start with it"""
|
755
|
-
if self.forceLbsram() is True:
|
756
|
-
if not self._qteFolderSelected.text().startswith(get_lbsram_path()):
|
757
|
-
self._qteFolderSelected.setText(self.__getOutputWithLbsramExtension())
|