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
@@ -35,6 +35,7 @@ from silx.gui import qt
|
|
35
35
|
from silx.gui.dialog.DataFileDialog import DataFileDialog
|
36
36
|
from silx.utils.enum import Enum as _Enum
|
37
37
|
|
38
|
+
from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
|
38
39
|
from tomwer.core.process.reconstruction.nabu.nabuslices import NabuSliceMode
|
39
40
|
from tomwer.core.process.reconstruction.nabu.utils import (
|
40
41
|
_NabuFBPFilterType,
|
@@ -300,55 +301,74 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
300
301
|
# come with an issue as we are on a scroll area
|
301
302
|
self._slicesWidget.setFocusPolicy(qt.Qt.FocusPolicy.NoFocus)
|
302
303
|
|
304
|
+
# axis
|
305
|
+
self._axisLabel = qt.QLabel("reconstruction plane", self)
|
306
|
+
self._axisLabel.setToolTip("Over which axis the slice must be picked")
|
307
|
+
self.layout().addWidget(self._axisLabel)
|
308
|
+
self._axisQCB = qt.QComboBox(self)
|
309
|
+
axis_tooltips = {
|
310
|
+
NabuPlane.YZ.value: "along axis x (aka axis 2 - expected to be slow)",
|
311
|
+
NabuPlane.XZ.value: "along axis y (aka axis 1 - expected to be slow)",
|
312
|
+
NabuPlane.XY.value: "along axis Z (aka axis 0 - fastest)",
|
313
|
+
}
|
314
|
+
for item, tooltip in axis_tooltips.items():
|
315
|
+
self._axisQCB.addItem(item)
|
316
|
+
self._axisQCB.setItemData(
|
317
|
+
self._axisQCB.findText(item),
|
318
|
+
tooltip,
|
319
|
+
qt.Qt.ToolTipRole,
|
320
|
+
)
|
321
|
+
self.layout().addWidget(self._axisQCB, 1, 1, 1, 1)
|
322
|
+
|
303
323
|
# method
|
304
324
|
self._methodLabel = qt.QLabel("method", self)
|
305
|
-
self.layout().addWidget(self._methodLabel,
|
325
|
+
self.layout().addWidget(self._methodLabel, 2, 0, 1, 1)
|
306
326
|
self._methodQCB = QComboBoxIgnoreWheel(parent=self, scrollArea=scrollArea)
|
307
327
|
for method in _NabuReconstructionMethods:
|
308
328
|
self._methodQCB.addItem(method.value)
|
309
|
-
self.layout().addWidget(self._methodQCB,
|
329
|
+
self.layout().addWidget(self._methodQCB, 2, 1, 1, 1)
|
310
330
|
self.registerWidget(self._methodLabel, "required")
|
311
331
|
self.registerWidget(self._methodQCB, "required")
|
312
332
|
|
313
333
|
# angle_offset
|
314
334
|
self._labelOffsetLabel = qt.QLabel("angle offset (in degree)", self)
|
315
|
-
self.layout().addWidget(self._labelOffsetLabel,
|
335
|
+
self.layout().addWidget(self._labelOffsetLabel, 3, 0, 1, 1)
|
316
336
|
self._angleOffsetQDSB = QDoubleSpinBoxIgnoreWheel(self, scrollArea)
|
317
337
|
self._angleOffsetQDSB.setMaximum(-180)
|
318
338
|
self._angleOffsetQDSB.setMaximum(180)
|
319
|
-
self.layout().addWidget(self._angleOffsetQDSB,
|
339
|
+
self.layout().addWidget(self._angleOffsetQDSB, 3, 1, 1, 1)
|
320
340
|
self.registerWidget(self._labelOffsetLabel, "advanced")
|
321
341
|
self.registerWidget(self._angleOffsetQDSB, "advanced")
|
322
342
|
|
323
343
|
# fbp filter type
|
324
344
|
self._fbpFilterCB = qt.QCheckBox("fbp filter", self)
|
325
|
-
self.layout().addWidget(self._fbpFilterCB,
|
345
|
+
self.layout().addWidget(self._fbpFilterCB, 4, 0, 1, 1)
|
326
346
|
self._fbpFilterType = QComboBoxIgnoreWheel(self, scrollArea)
|
327
347
|
for filter_type in _NabuFBPFilterType:
|
328
348
|
self._fbpFilterType.addItem(filter_type.value)
|
329
|
-
self.layout().addWidget(self._fbpFilterType,
|
349
|
+
self.layout().addWidget(self._fbpFilterType, 4, 1, 1, 1)
|
330
350
|
self.registerWidget(self._fbpFilterCB, "advanced")
|
331
351
|
self.registerWidget(self._fbpFilterType, "advanced")
|
332
352
|
|
333
353
|
# padding type
|
334
354
|
self._paddingTypeLabel = qt.QLabel("padding type", self)
|
335
|
-
self.layout().addWidget(self._paddingTypeLabel,
|
355
|
+
self.layout().addWidget(self._paddingTypeLabel, 5, 0, 1, 1)
|
336
356
|
self._paddingType = QComboBoxIgnoreWheel(self, scrollArea)
|
337
357
|
for fbp_padding_type in _NabuPaddingType:
|
338
358
|
self._paddingType.addItem(fbp_padding_type.value)
|
339
|
-
self.layout().addWidget(self._paddingType,
|
359
|
+
self.layout().addWidget(self._paddingType, 5, 1, 1, 1)
|
340
360
|
self.registerWidget(self._paddingTypeLabel, "optional")
|
341
361
|
self.registerWidget(self._paddingType, "optional")
|
342
362
|
|
343
363
|
# sub region
|
344
364
|
self._subRegionSelector = _NabuReconstructionSubRegion(parent=self)
|
345
|
-
self.layout().addWidget(self._subRegionSelector,
|
365
|
+
self.layout().addWidget(self._subRegionSelector, 7, 0, 1, 2)
|
346
366
|
|
347
367
|
# iterations
|
348
368
|
self._iterationsLabel = qt.QLabel("iterations", self)
|
349
|
-
self.layout().addWidget(self._iterationsLabel,
|
369
|
+
self.layout().addWidget(self._iterationsLabel, 8, 0, 1, 1)
|
350
370
|
self._iterationSB = qt.QSpinBox(parent=self)
|
351
|
-
self.layout().addWidget(self._iterationSB,
|
371
|
+
self.layout().addWidget(self._iterationSB, 8, 1, 1, 1)
|
352
372
|
self._iterationSB.setMinimum(1)
|
353
373
|
self._iterationSB.setMaximum(9999)
|
354
374
|
# not supported for now so hidden
|
@@ -359,14 +379,14 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
359
379
|
self._binSubSamplingGB = _BinSubSampling(
|
360
380
|
"binning and subsampling", parent=self, scrollArea=scrollArea
|
361
381
|
)
|
362
|
-
self.layout().addWidget(self._binSubSamplingGB,
|
382
|
+
self.layout().addWidget(self._binSubSamplingGB, 9, 0, 1, 2)
|
363
383
|
|
364
384
|
# optimization algorithm:
|
365
385
|
# set has default value for now, because has only one at the moment
|
366
386
|
|
367
387
|
# weight total variation
|
368
388
|
self._tvLabel = qt.QLabel("total variation weight", self)
|
369
|
-
self.layout().addWidget(self._tvLabel,
|
389
|
+
self.layout().addWidget(self._tvLabel, 10, 0, 1, 1)
|
370
390
|
self._totalVariationWeight = qt.QDoubleSpinBox(self)
|
371
391
|
self._totalVariationWeight.setMinimum(0.0)
|
372
392
|
self._totalVariationWeight.setMaximum(1.0)
|
@@ -382,7 +402,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
382
402
|
self._preconditioningFilter.setToolTip(
|
383
403
|
'Whether to enable "filter ' 'preconditioning" for iterative' " methods"
|
384
404
|
)
|
385
|
-
self.layout().addWidget(self._preconditioningFilter,
|
405
|
+
self.layout().addWidget(self._preconditioningFilter, 10, 0, 1, 2)
|
386
406
|
# not supported for now so hidden
|
387
407
|
self._preconditioningFilter.hide()
|
388
408
|
|
@@ -391,7 +411,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
391
411
|
self._positivityConstraintCB.setToolTip(
|
392
412
|
"Whether to enforce a " "positivity constraint in the " "reconstruction."
|
393
413
|
)
|
394
|
-
self.layout().addWidget(self._positivityConstraintCB,
|
414
|
+
self.layout().addWidget(self._positivityConstraintCB, 11, 0, 1, 2)
|
395
415
|
# not supported for now so hidden
|
396
416
|
self._positivityConstraintCB.hide()
|
397
417
|
|
@@ -400,28 +420,28 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
400
420
|
self._clipOuterCircleCB.setToolTip(
|
401
421
|
"Whether to set to zero voxels falling outside of the reconstruction region"
|
402
422
|
)
|
403
|
-
self.layout().addWidget(self._clipOuterCircleCB,
|
423
|
+
self.layout().addWidget(self._clipOuterCircleCB, 12, 0, 1, 2)
|
404
424
|
self.registerWidget(self._clipOuterCircleCB, "optional")
|
405
425
|
|
406
426
|
# centered axis option
|
407
427
|
self._centeredAxisCB = qt.QCheckBox("centered axis", self)
|
408
428
|
self._centeredAxisCB.setToolTip("")
|
409
|
-
self.layout().addWidget(self._centeredAxisCB,
|
429
|
+
self.layout().addWidget(self._centeredAxisCB, 13, 0, 1, 2)
|
410
430
|
self.registerWidget(self._centeredAxisCB, "optional")
|
411
431
|
|
412
432
|
# translation movement file
|
413
433
|
self._transMvtFileLabel = qt.QLabel("translation movement file", self)
|
414
|
-
self.layout().addWidget(self._transMvtFileLabel,
|
434
|
+
self.layout().addWidget(self._transMvtFileLabel, 22, 0, 1, 1)
|
415
435
|
self._transMvtFileWidget = TranslationMvtFileWidget(self)
|
416
|
-
self.layout().addWidget(self._transMvtFileWidget,
|
436
|
+
self.layout().addWidget(self._transMvtFileWidget, 22, 1, 1, 1)
|
417
437
|
self.registerWidget(self._transMvtFileLabel, "advanced")
|
418
438
|
self.registerWidget(self._transMvtFileWidget, "advanced")
|
419
439
|
|
420
440
|
# angle files (if the user want's to overwrite rotation angles)
|
421
441
|
self._angleFileLabel = qt.QLabel("angles file", self)
|
422
|
-
self.layout().addWidget(self._angleFileLabel,
|
442
|
+
self.layout().addWidget(self._angleFileLabel, 23, 0, 1, 1)
|
423
443
|
self._anglesFileWidget = AnglesFileWidget(self)
|
424
|
-
self.layout().addWidget(self._anglesFileWidget,
|
444
|
+
self.layout().addWidget(self._anglesFileWidget, 23, 1, 1, 1)
|
425
445
|
self.registerWidget(self._angleFileLabel, "advanced")
|
426
446
|
self.registerWidget(self._anglesFileWidget, "advanced")
|
427
447
|
|
@@ -431,6 +451,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
431
451
|
self.layout().addWidget(spacer, 200, 1, 1, 1)
|
432
452
|
|
433
453
|
# set up
|
454
|
+
self.setNabuPlane("XY")
|
434
455
|
self._fbpFilterCB.setChecked(True)
|
435
456
|
fbp_item = self._methodQCB.findText(_NabuReconstructionMethods.FBP.value)
|
436
457
|
self._methodQCB.setCurrentIndex(fbp_item)
|
@@ -447,6 +468,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
447
468
|
self._centeredAxisCB.setChecked(False)
|
448
469
|
|
449
470
|
# connect signal / slot
|
471
|
+
self._axisQCB.currentIndexChanged.connect(self._slicesChanged)
|
450
472
|
self._methodQCB.currentIndexChanged.connect(self._methodChanged)
|
451
473
|
self._angleOffsetQDSB.editingFinished.connect(self._angleOffsetChanged)
|
452
474
|
self._fbpFilterCB.toggled.connect(self._FBPFilterTypeChanged)
|
@@ -628,6 +650,14 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
628
650
|
def setCenteredAxis(self, checked: bool):
|
629
651
|
self._centeredAxisCB.setChecked(checked)
|
630
652
|
|
653
|
+
def getNabuPlane(self) -> NabuPlane:
|
654
|
+
"""return over which axis we expect to do the reconstruction"""
|
655
|
+
return NabuPlane.from_value(self._axisQCB.currentText())
|
656
|
+
|
657
|
+
def setNabuPlane(self, axis: typing.Union[str, NabuPlane]):
|
658
|
+
axis = NabuPlane.from_value(axis)
|
659
|
+
self._axisQCB.setCurrentText(axis.value)
|
660
|
+
|
631
661
|
@docstring(_NabuStageConfigBase)
|
632
662
|
def getConfiguration(self) -> dict:
|
633
663
|
fbp_filter_type = self.getFBPFilterType()
|
@@ -637,6 +667,7 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
637
667
|
fbp_filter_type = fbp_filter_type.value
|
638
668
|
config = {
|
639
669
|
"method": self.getMethod().value,
|
670
|
+
"slice_plane": self.getNabuPlane().value,
|
640
671
|
"angles_file": self.getAnglesFile(),
|
641
672
|
"axis_correction_file": "", # not managed for now
|
642
673
|
"angle_offset": self.getAngleOffset(),
|
@@ -689,6 +720,8 @@ class _NabuReconstructionConfig(qt.QWidget, _NabuStageConfigBase):
|
|
689
720
|
self.setClipOuterCircle(bool(config["clip_outer_circle"]))
|
690
721
|
if "centered_axis" in config:
|
691
722
|
self.setCenteredAxis(bool(config["centered_axis"]))
|
723
|
+
if "slice_plane" in config:
|
724
|
+
self.setNabuPlane(config["slice_plane"])
|
692
725
|
self._subRegionSelector.setConfiguration(config=config)
|
693
726
|
|
694
727
|
def _signalConfChanged(self, param):
|
@@ -96,11 +96,6 @@ class SinoNormWindow(qt.QMainWindow):
|
|
96
96
|
self._centralWidget._updateSinogramROI()
|
97
97
|
self._modeChanged()
|
98
98
|
|
99
|
-
def close(self):
|
100
|
-
self._centralWidget.stop()
|
101
|
-
self._centralWidget = None
|
102
|
-
super().close()
|
103
|
-
|
104
99
|
def _hideLockButton(self):
|
105
100
|
self._optsWidget._hideLockButton()
|
106
101
|
|
@@ -165,11 +160,6 @@ class SinoNormWindow(qt.QMainWindow):
|
|
165
160
|
self._centralWidget.setScan(scan=scan)
|
166
161
|
self._optsWidget.setScan(scan=scan)
|
167
162
|
|
168
|
-
def stop(self):
|
169
|
-
if self._centralWidget is not None:
|
170
|
-
self._centralWidget.stop()
|
171
|
-
self._centralWidget = None
|
172
|
-
|
173
163
|
def getExtraArgs(self) -> dict:
|
174
164
|
return self._optsWidget.getExtraInfos()
|
175
165
|
|
@@ -246,12 +236,6 @@ class _Viewer(qt.QTabWidget):
|
|
246
236
|
self._projView.setManualROIVisible(visible=visible)
|
247
237
|
self._sinoView.setROIVisible(visible=visible)
|
248
238
|
|
249
|
-
def stop(self):
|
250
|
-
self._projView.stop()
|
251
|
-
self._projView = None
|
252
|
-
self._sinoView.stop()
|
253
|
-
self._sinoView = None
|
254
|
-
|
255
239
|
def getROI(self):
|
256
240
|
return self._projView.getROI()
|
257
241
|
|
@@ -341,9 +325,6 @@ class _ProjPlotWithROI(DataViewer):
|
|
341
325
|
super().clear()
|
342
326
|
self.getPlotWidget().removeMarker("sinogram_line")
|
343
327
|
|
344
|
-
def stop(self):
|
345
|
-
self._viewer._plot.stopUpdateThread()
|
346
|
-
|
347
328
|
|
348
329
|
class SinogramViewer(_SinogramViewer):
|
349
330
|
""" "Sinogram viewer but adapated for Intensity normalization"""
|
@@ -397,14 +378,11 @@ class SinogramViewer(_SinogramViewer):
|
|
397
378
|
self.getPlotWidget().addItem(item)
|
398
379
|
|
399
380
|
def getPlotWidget(self):
|
400
|
-
return self._plot
|
381
|
+
return self._plot
|
401
382
|
|
402
383
|
def _updatePlot(self, sinogram):
|
403
|
-
self.
|
404
|
-
self.
|
405
|
-
|
406
|
-
def stop(self):
|
407
|
-
self._plot.stopUpdateThread()
|
384
|
+
self.getPlotWidget().addImage(data=sinogram)
|
385
|
+
self.getPlotWidget().replot()
|
408
386
|
|
409
387
|
|
410
388
|
class _NormIntensityOptions(qt.QWidget):
|
@@ -148,7 +148,7 @@ class SinogramViewer(_SinogramViewer):
|
|
148
148
|
self._estimated_cor = estimated_cor
|
149
149
|
self._other_cors = other_cors if other_cors is not None else tuple()
|
150
150
|
|
151
|
-
plot = self._plot
|
151
|
+
plot = self._plot
|
152
152
|
|
153
153
|
if self._corMarker is not None:
|
154
154
|
self._corMarker.sigDragFinished.disconnect(self._middleMarkerMoved)
|
@@ -303,10 +303,6 @@ class _SAAxisTabWidget(qt.QTabWidget):
|
|
303
303
|
self._nabuSettings = None
|
304
304
|
super().close()
|
305
305
|
|
306
|
-
def _stopAnimationThread(self):
|
307
|
-
self._resultsViewer._stopAnimationThread()
|
308
|
-
self._sliceAndCorWidget._sinogramViewer._stopAnimationThread()
|
309
|
-
|
310
306
|
|
311
307
|
class SAAxisWindow(qt.QMainWindow):
|
312
308
|
"""
|
@@ -381,9 +377,6 @@ class SAAxisWindow(qt.QMainWindow):
|
|
381
377
|
self._saaxisControl.sigComputationRequest.connect(self._launchReconstructions)
|
382
378
|
self._saaxisControl.sigValidateRequest.connect(self._validate)
|
383
379
|
|
384
|
-
def stop(self):
|
385
|
-
self._stopAnimationThread()
|
386
|
-
|
387
380
|
def showResults(self):
|
388
381
|
self._tabWidget.showResults()
|
389
382
|
|
@@ -451,7 +444,7 @@ class SAAxisWindow(qt.QMainWindow):
|
|
451
444
|
def _updateSinogramLine(self):
|
452
445
|
r_slice = self.getReconstructionSlices()
|
453
446
|
if r_slice == "middle":
|
454
|
-
line = slice_index_to_int(slice_index="middle", scan=self._scan)
|
447
|
+
line = slice_index_to_int(slice_index="middle", scan=self._scan, axis="XY")
|
455
448
|
else:
|
456
449
|
line = list(r_slice.values())[0]
|
457
450
|
self._tabWidget.getSinogramViewer().setLine(line)
|
@@ -507,9 +500,6 @@ class SAAxisWindow(qt.QMainWindow):
|
|
507
500
|
if idx >= 0:
|
508
501
|
self._tabWidget.setCurrentIndex(idx)
|
509
502
|
|
510
|
-
def _stopAnimationThread(self):
|
511
|
-
self._tabWidget._stopAnimationThread()
|
512
|
-
|
513
503
|
def close(self):
|
514
504
|
self._tabWidget.close()
|
515
505
|
self._tabWidget = None
|
@@ -239,7 +239,6 @@ class _SADeltaBetaTabWidget(qt.QTabWidget):
|
|
239
239
|
self._resultsViewer.setScoreMethod(method)
|
240
240
|
|
241
241
|
def close(self):
|
242
|
-
self._stopAnimationThread()
|
243
242
|
self._resultsViewer.close()
|
244
243
|
self._resultsViewer = None
|
245
244
|
self._deltaBetaSelectionWidget.close()
|
@@ -248,9 +247,6 @@ class _SADeltaBetaTabWidget(qt.QTabWidget):
|
|
248
247
|
self._nabuSettings = None
|
249
248
|
super().close()
|
250
249
|
|
251
|
-
def _stopAnimationThread(self):
|
252
|
-
self._resultsViewer._stopAnimationThread()
|
253
|
-
|
254
250
|
def setSliceRange(self, min_, max_):
|
255
251
|
self._deltaBetaSelectionWidget.setSliceRange(min_, max_)
|
256
252
|
|
@@ -357,12 +353,6 @@ class SADeltaBetaWindow(qt.QMainWindow):
|
|
357
353
|
self._tabWidget = None
|
358
354
|
super().close()
|
359
355
|
|
360
|
-
def stop(self):
|
361
|
-
self._stopAnimationThread()
|
362
|
-
|
363
|
-
def _stopAnimationThread(self):
|
364
|
-
self._tabWidget._stopAnimationThread()
|
365
|
-
|
366
356
|
def setDBScores(
|
367
357
|
self,
|
368
358
|
scores: dict,
|
@@ -612,12 +612,7 @@ class ScorePlot(qt.QWidget):
|
|
612
612
|
self.sigConfigurationChanged.emit()
|
613
613
|
|
614
614
|
def getPlotWidget(self):
|
615
|
-
return self._plot
|
616
|
-
|
617
|
-
def _stopAnimationThread(self):
|
618
|
-
self._plot._freeLoadingThreads()
|
619
|
-
if self._plot._plot.updateThread.is_alive():
|
620
|
-
self._plot._plot.updateThread.stop()
|
615
|
+
return self._plot
|
621
616
|
|
622
617
|
def close(self):
|
623
618
|
self._plot.close()
|
@@ -74,19 +74,33 @@ class TestWindowAxis(TestCaseQt):
|
|
74
74
|
def testSetImagesNumpyArray(self):
|
75
75
|
"""Test the setImages function"""
|
76
76
|
radio_axis = self._window._axisWidget._radioAxis
|
77
|
-
self.
|
77
|
+
radio_axis_plot = self._window._axisWidget._radioAxis.getPlot()
|
78
|
+
numpy.testing.assert_array_equal(
|
79
|
+
radio_axis_plot.getPlot().getActiveImage().getData(), numpy.empty((0, 0, 4))
|
80
|
+
)
|
78
81
|
imgA = numpy.random.random((100, 100))
|
79
82
|
imgB = numpy.random.random((100, 100))
|
80
83
|
radio_axis.setImages(imgA=imgA, imgB=imgB, flipB=True)
|
81
84
|
self.qapp.processEvents()
|
82
|
-
|
85
|
+
# make sur the image has been set
|
86
|
+
assert radio_axis_plot.getPlot().getImage(legend="image1").getData().shape == (
|
87
|
+
100,
|
88
|
+
100,
|
89
|
+
)
|
83
90
|
|
84
91
|
def testSetScan(self):
|
85
92
|
"""Test the setScan function"""
|
86
93
|
radio_axis_plot = self._window._axisWidget._radioAxis.getPlot()
|
87
|
-
|
94
|
+
numpy.testing.assert_array_equal(
|
95
|
+
radio_axis_plot.getPlot().getActiveImage().getData(), numpy.empty((0, 0, 4))
|
96
|
+
)
|
88
97
|
self._window.setScan(self.scan)
|
89
|
-
self.
|
98
|
+
self.qapp.processEvents()
|
99
|
+
# make sur the image has been set
|
100
|
+
assert radio_axis_plot.getPlot().getImage(legend="image1").getData().shape == (
|
101
|
+
20,
|
102
|
+
20,
|
103
|
+
)
|
90
104
|
|
91
105
|
def testShiftButtons(self):
|
92
106
|
"""Test that the 'left', 'right', ... buttons and the shift steps are
|
@@ -219,6 +219,7 @@ class TestNabuReconstructionConfig(TestCaseQt):
|
|
219
219
|
"""Test that the get configuration is working"""
|
220
220
|
ini_conf = {
|
221
221
|
"method": "FBP",
|
222
|
+
"slice_plane": "XY",
|
222
223
|
"angles_file": "",
|
223
224
|
"axis_correction_file": "",
|
224
225
|
"angle_offset": 0.0,
|
@@ -246,6 +247,7 @@ class TestNabuReconstructionConfig(TestCaseQt):
|
|
246
247
|
"""Test that the set configuration is working"""
|
247
248
|
ini_conf = {
|
248
249
|
"method": "FBP",
|
250
|
+
"slice_plane": "XZ",
|
249
251
|
"angles_file": "",
|
250
252
|
"axis_correction_file": "",
|
251
253
|
"angle_offset": 12.5,
|
@@ -284,6 +286,7 @@ class TestNabuReconstructionConfig(TestCaseQt):
|
|
284
286
|
self.assertFalse(self.nabuWidget._preconditioningFilter.isChecked())
|
285
287
|
self.assertTrue(self.nabuWidget._clipOuterCircleCB.isChecked())
|
286
288
|
self.assertTrue(self.nabuWidget._centeredAxisCB.isChecked())
|
289
|
+
assert self.nabuWidget._axisQCB.currentText() == ini_conf["slice_plane"]
|
287
290
|
|
288
291
|
# check the generated configuration
|
289
292
|
self.assertEqual(self.nabuWidget.getConfiguration(), ini_conf)
|
@@ -727,7 +727,7 @@ class ZStitchingWindow(qt.QMainWindow):
|
|
727
727
|
|
728
728
|
# clean current preview to notify some calculation is going on
|
729
729
|
preview_plot = self._widget._mainWidget._previewPlot
|
730
|
-
preview_plot.
|
730
|
+
preview_plot._waitingOverlay.show()
|
731
731
|
|
732
732
|
# start sitching on a thread
|
733
733
|
self._previewThread = PreviewThread(stitching_config=config)
|
@@ -749,7 +749,7 @@ class ZStitchingWindow(qt.QMainWindow):
|
|
749
749
|
output_obj_identifier = sender.output_identifier
|
750
750
|
|
751
751
|
preview_plot = self._widget._mainWidget._previewPlot
|
752
|
-
preview_plot.
|
752
|
+
preview_plot._waitingOverlay.hide()
|
753
753
|
|
754
754
|
self._previewThread.finished.disconnect(self._previewCalculationFinished)
|
755
755
|
self._previewThread = None
|
@@ -14,14 +14,9 @@ from tomwer.core.volume.volumefactory import VolumeFactory
|
|
14
14
|
from tomwer.gui import icons as tomwer_icons
|
15
15
|
from tomwer.gui import settings
|
16
16
|
from tomwer.gui.stitching.stitchandbackground import StitchAndBackgroundAlphaMixIn
|
17
|
-
from silx.gui.plot import Plot2D, items
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
PlotWithWaitingLabel as _PlotWithWaitingLabel,
|
22
|
-
)
|
23
|
-
except ImportError:
|
24
|
-
from silx.gui.plot.ImageStack import _PlotWithWaitingLabel # noqa F401
|
18
|
+
from silx.gui.plot import Plot2D, items
|
19
|
+
from silx.gui.widgets.WaitingOverlay import WaitingOverlay
|
25
20
|
|
26
21
|
_logger = logging.getLogger(__name__)
|
27
22
|
|
@@ -62,22 +57,23 @@ class _PreviewPlot2D(Plot2D):
|
|
62
57
|
return "-" # No image picked
|
63
58
|
|
64
59
|
|
65
|
-
class PreviewStitchingPlot(
|
60
|
+
class PreviewStitchingPlot(Plot2D, StitchAndBackgroundAlphaMixIn):
|
66
61
|
DEFAULT_STITCHED_IMG_ALPHA = 0.95
|
67
62
|
DEFAULT_BACKGROUND_IMG_ALPHA = 0.20
|
68
63
|
|
69
64
|
def __init__(self, parent=None) -> None:
|
70
65
|
super().__init__(parent=parent) # pylint: disable=E1123
|
66
|
+
self._waitingOverlay = WaitingOverlay(self)
|
67
|
+
self._waitingOverlay.setIconSize(qt.QSize(30, 30))
|
71
68
|
self._stitched_image = None
|
72
69
|
self._composition_background = None
|
73
70
|
|
74
71
|
# replace the simple Plot2D by a `_PreviewPlot2D` (to filter overlay image value to be displayed)
|
75
|
-
self.layout().removeWidget(self._plot)
|
76
72
|
self._plot = _PreviewPlot2D(parent=self)
|
77
73
|
self.layout().addWidget(self._plot)
|
78
74
|
|
79
75
|
# tune plot
|
80
|
-
self.
|
76
|
+
self.setYAxisInverted(settings.Y_AXIS_DOWNWARD)
|
81
77
|
# by default we want to have a full screen display
|
82
78
|
self.setAxesDisplayed(False)
|
83
79
|
|
@@ -110,7 +106,7 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
110
106
|
# set up
|
111
107
|
self.setAlphaBackgroundImg(value=self.DEFAULT_BACKGROUND_IMG_ALPHA)
|
112
108
|
self.setAlphaStitchedImg(value=self.DEFAULT_STITCHED_IMG_ALPHA)
|
113
|
-
self.
|
109
|
+
self._waitingOverlay.hide()
|
114
110
|
|
115
111
|
# connect signal / slot
|
116
112
|
self._backGroundAction.toggled.connect(self._update)
|
@@ -249,48 +245,6 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
249
245
|
def stitched_image(self):
|
250
246
|
return self._stitched_image
|
251
247
|
|
252
|
-
# expose API
|
253
|
-
def getImage(self, *args, **kwargs):
|
254
|
-
return self.getPlotWidget().getImage(*args, **kwargs)
|
255
|
-
|
256
|
-
def addImage(self, *args, **kwargs):
|
257
|
-
self.getPlotWidget().addImage(*args, **kwargs)
|
258
|
-
|
259
|
-
def removeImage(self, *args, **kwargs):
|
260
|
-
self.getPlotWidget().removeImage(*args, **kwargs)
|
261
|
-
|
262
|
-
def toolBar(self, *args, **kwargs):
|
263
|
-
return self.getPlotWidget().toolBar(*args, **kwargs)
|
264
|
-
|
265
|
-
def setKeepDataAspectRatio(self, *args, **kwargs):
|
266
|
-
return self.getPlotWidget().setKeepDataAspectRatio(*args, **kwargs)
|
267
|
-
|
268
|
-
def getColorBarWidget(self, *args, **kwargs):
|
269
|
-
return self.getPlotWidget().getColorBarWidget(*args, **kwargs)
|
270
|
-
|
271
|
-
def getMaskAction(self, *args, **kwargs):
|
272
|
-
return self.getPlotWidget().getMaskAction(*args, **kwargs)
|
273
|
-
|
274
|
-
def getCopyAction(self, *args, **kwargs):
|
275
|
-
return self.getPlotWidget().getCopyAction(*args, **kwargs)
|
276
|
-
|
277
|
-
def addToolBar(self, *args, **kwargs):
|
278
|
-
return self.getPlotWidget().addToolBar(*args, **kwargs)
|
279
|
-
|
280
|
-
def setActiveImage(self, *args, **kwargs):
|
281
|
-
return self.getPlotWidget().setActiveImage(*args, **kwargs)
|
282
|
-
|
283
|
-
def setAxesDisplayed(self, *args, **kwargs):
|
284
|
-
plotWidget = self.getPlotWidget()
|
285
|
-
if hasattr(plotWidget, "setAxesDisplayed"):
|
286
|
-
plotWidget.setAxesDisplayed(*args, **kwargs)
|
287
|
-
|
288
|
-
def getDefaultColormap(self, *args, **kwargs):
|
289
|
-
return self.getPlotWidget().getDefaultColormap()
|
290
|
-
|
291
|
-
def setDefaultColormap(self, *args, **kwargs):
|
292
|
-
return self.getPlotWidget().setDefaultColormap(*args, **kwargs)
|
293
|
-
|
294
248
|
def setPixelSize(self, pixel_size: Union[tuple, float]):
|
295
249
|
"""set the pixel size to be used by the ruler"""
|
296
250
|
self._tapeMeasureButton.setPixelSize(pixel_size_m=pixel_size)
|
@@ -189,9 +189,9 @@ class RawStitchingPlot(PlotWindow):
|
|
189
189
|
|
190
190
|
self._alphaValuesWidget.addTomoObj(tomo_obj)
|
191
191
|
if isinstance(tomo_obj, TomwerScanBase):
|
192
|
-
self._scan_reading_order[
|
193
|
-
|
194
|
-
|
192
|
+
self._scan_reading_order[tomo_obj.get_identifier().to_str()] = (
|
193
|
+
self.getRotationAngleDirection(tomo_obj)
|
194
|
+
)
|
195
195
|
if first_tomo_obj_id != tuple(self._tomo_objs.keys())[0]:
|
196
196
|
# if the order of scans might have change we need to update the full stack (to handle reading order)
|
197
197
|
self._updateImages()
|
tomwer/gui/utils/inputwidget.py
CHANGED
@@ -360,9 +360,9 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
360
360
|
self._manualRB.setChecked(True)
|
361
361
|
else:
|
362
362
|
if default_output is ProcessDataOutputDirMode.IN_SCAN_FOLDER:
|
363
|
-
self._processedDataFolderRB.setChecked(True)
|
364
|
-
elif default_output is ProcessDataOutputDirMode.PROCESSED_DATA_FOLDER:
|
365
363
|
self._inScanFolder.setChecked(True)
|
364
|
+
elif default_output is ProcessDataOutputDirMode.PROCESSED_DATA_FOLDER:
|
365
|
+
self._processedDataFolderRB.setChecked(True)
|
366
366
|
elif default_output is ProcessDataOutputDirMode.RAW_DATA_FOLDER:
|
367
367
|
self._rawDataFolderRB.setChecked(True)
|
368
368
|
else:
|
@@ -524,6 +524,11 @@ class OutputVolumeDefinition(qt.QWidget):
|
|
524
524
|
os.environ["TOMWER_DEFAULT_INPUT_DIR"]
|
525
525
|
):
|
526
526
|
dialog.setDirectory(os.environ["TOMWER_DEFAULT_INPUT_DIR"])
|
527
|
+
elif dialog.directory() != os.getcwd() or str(dialog.directory()).startswith(
|
528
|
+
"/data"
|
529
|
+
):
|
530
|
+
# if the directory as already been set by the user. Avoid redefining it
|
531
|
+
pass
|
527
532
|
elif os.path.isdir("/data"):
|
528
533
|
dialog.setDirectory("/data")
|
529
534
|
|
@@ -540,6 +545,11 @@ class OutputVolumeDefinition(qt.QWidget):
|
|
540
545
|
os.environ["TOMWER_DEFAULT_INPUT_DIR"]
|
541
546
|
):
|
542
547
|
dialog.setDirectory(os.environ["TOMWER_DEFAULT_INPUT_DIR"])
|
548
|
+
elif dialog.directory() != os.getcwd() or str(dialog.directory()).startswith(
|
549
|
+
"/data"
|
550
|
+
):
|
551
|
+
# if the directory as already been set by the user. Avoid redefining it
|
552
|
+
pass
|
543
553
|
elif os.path.isdir("/data"):
|
544
554
|
dialog.setDirectory("/data")
|
545
555
|
|
@@ -219,7 +219,7 @@ class QLineSelector(qt.QWidget):
|
|
219
219
|
"""
|
220
220
|
legend = self._getLegend(row_n=row)
|
221
221
|
if legend in self.__selection:
|
222
|
-
self._plot.
|
222
|
+
self._plot.remove(legend=legend, kind="item")
|
223
223
|
del self.__selection[legend]
|
224
224
|
|
225
225
|
def _plotDrawEvent(self, event):
|