tomwer 1.2.1__py3-none-any.whl → 1.3.12__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/icat_publication.ows +58 -0
- orangecontrib/tomwer/widgets/__init__.py +11 -11
- orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +2 -2
- orangecontrib/tomwer/widgets/control/DataListOW.py +9 -7
- orangecontrib/tomwer/widgets/control/DataListenerOW.py +6 -6
- orangecontrib/tomwer/widgets/control/DataSelectorOW.py +21 -10
- orangecontrib/tomwer/widgets/control/DataValidatorOW.py +6 -6
- orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +24 -7
- orangecontrib/tomwer/widgets/control/EmailOW.py +4 -4
- orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +3 -3
- orangecontrib/tomwer/widgets/control/NXTomomillOW.py +64 -23
- orangecontrib/tomwer/widgets/control/NXtomoConcatenate.py +20 -8
- orangecontrib/tomwer/widgets/control/NotifierOW.py +1 -0
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +6 -6
- orangecontrib/tomwer/widgets/control/VolumeSelector.py +7 -4
- orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +182 -182
- orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +5 -5
- orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +4 -4
- orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +3 -3
- orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +8 -1
- orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +3 -3
- orangecontrib/tomwer/widgets/edit/test/test_nxtomo_editor.py +3 -3
- orangecontrib/tomwer/widgets/icat/PublishProcessedDataOW.py +115 -0
- orangecontrib/tomwer/widgets/icat/RawDataScreenshotCreatorOW.py +98 -0
- orangecontrib/tomwer/widgets/icat/SaveToGalleryAndPublishOW.py +129 -0
- orangecontrib/tomwer/widgets/icat/__init__.py +13 -0
- orangecontrib/tomwer/widgets/icat/icons/add_gallery.png +0 -0
- orangecontrib/tomwer/widgets/icat/icons/add_gallery.svg +82 -0
- orangecontrib/tomwer/widgets/icat/icons/publish_processed_data.png +0 -0
- orangecontrib/tomwer/widgets/icat/icons/publish_processed_data.svg +95 -0
- orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.png +0 -0
- orangecontrib/tomwer/widgets/icat/icons/raw_screenshots.svg +143 -0
- orangecontrib/tomwer/widgets/icons/tomwer_data_portal.png +0 -0
- orangecontrib/tomwer/widgets/icons/tomwer_data_portal.svg +76 -0
- orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +22 -20
- orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +19 -3
- orangecontrib/tomwer/widgets/reconstruction/NabuHelicalPrepareWeightsDoubleOW.py +184 -169
- orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +23 -0
- orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +39 -5
- orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +18 -22
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +18 -26
- orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +15 -19
- orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +9 -9
- orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +3 -3
- orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/VolumeViewerOW.py +3 -29
- tomwer/__main__.py +7 -64
- tomwer/app/axis.py +3 -3
- tomwer/app/canvas.py +8 -0
- tomwer/app/canvas_launcher/config.py +16 -14
- tomwer/app/canvas_launcher/environ.py +1 -0
- tomwer/app/canvas_launcher/mainwindow.py +4 -1
- tomwer/app/darkref.py +1 -1
- tomwer/app/darkrefpatch.py +1 -1
- tomwer/app/diffframe.py +3 -3
- tomwer/app/imagekeyeditor.py +5 -5
- tomwer/app/imagekeyupgrader.py +5 -5
- tomwer/app/intensitynormalization.py +14 -13
- tomwer/app/{saaxis.py → multicor.py} +3 -3
- tomwer/app/{sadeltabeta.py → multipag.py} +3 -3
- tomwer/app/nabuapp.py +0 -11
- tomwer/app/radiostack.py +6 -4
- tomwer/app/samplemoved.py +3 -2
- tomwer/app/scanviewer.py +4 -2
- tomwer/app/sinogramviewer.py +3 -2
- tomwer/app/slicestack.py +3 -2
- tomwer/app/zstitching.py +88 -6
- tomwer/core/cluster/cluster.py +26 -0
- tomwer/core/log/logger.py +7 -5
- tomwer/core/process/conditions/filters.py +1 -1
- tomwer/core/process/control/datalistener/datalistener.py +19 -14
- tomwer/core/process/control/datawatcher/edfdwprocess.py +0 -9
- tomwer/core/process/control/nxtomoconcatenate.py +13 -13
- tomwer/core/process/control/nxtomomill.py +92 -34
- tomwer/core/process/control/scantransfer.py +20 -43
- tomwer/core/process/control/scanvalidator.py +3 -2
- tomwer/core/process/control/test/test_concatenate_nxtomos.py +9 -9
- tomwer/core/process/control/test/test_email.py +4 -4
- tomwer/core/process/control/test/test_h52nx_process.py +59 -7
- tomwer/core/process/control/test/test_volume_link.py +64 -64
- tomwer/core/process/control/timer.py +1 -1
- tomwer/core/process/control/volumesymlink.py +200 -200
- tomwer/core/process/edit/darkflatpatch.py +14 -15
- tomwer/core/process/edit/imagekeyeditor.py +41 -39
- tomwer/core/process/icat/__init__.py +0 -0
- tomwer/core/process/icat/createscreenshots.py +100 -0
- tomwer/core/process/icat/gallery.py +377 -0
- tomwer/core/process/icat/icatbase.py +36 -0
- tomwer/core/process/icat/publish.py +228 -0
- tomwer/core/process/icat/screenshots.py +27 -0
- tomwer/core/process/output.py +52 -0
- tomwer/core/process/reconstruction/axis/axis.py +280 -69
- tomwer/core/process/reconstruction/axis/mode.py +163 -48
- tomwer/core/process/reconstruction/axis/params.py +29 -21
- tomwer/core/process/reconstruction/darkref/darkrefs.py +41 -127
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +4 -3
- tomwer/core/process/reconstruction/darkref/params.py +1 -1
- tomwer/core/process/reconstruction/nabu/castvolume.py +4 -4
- tomwer/core/process/reconstruction/nabu/helical.py +9 -5
- tomwer/core/process/reconstruction/nabu/nabucommon.py +71 -78
- tomwer/core/process/reconstruction/nabu/nabuscores.py +425 -53
- tomwer/core/process/reconstruction/nabu/nabuslices.py +114 -93
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +54 -27
- tomwer/core/process/reconstruction/nabu/plane.py +9 -0
- tomwer/core/process/reconstruction/nabu/settings.py +2 -2
- tomwer/core/process/reconstruction/nabu/utils.py +164 -26
- tomwer/core/process/reconstruction/output.py +108 -0
- tomwer/core/process/reconstruction/saaxis/saaxis.py +238 -264
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +151 -87
- tomwer/core/process/reconstruction/scores/params.py +7 -4
- tomwer/core/process/reconstruction/scores/scores.py +13 -0
- tomwer/core/process/reconstruction/test/test_axis_params.py +2 -2
- tomwer/core/process/reconstruction/test/test_darkref.py +3 -3
- tomwer/core/process/reconstruction/test/test_darkref_copy.py +7 -7
- tomwer/core/process/reconstruction/test/test_saaxis.py +3 -4
- tomwer/core/process/reconstruction/test/test_sadeltabeta.py +2 -2
- tomwer/core/process/stitching/nabustitcher.py +13 -12
- tomwer/core/process/task.py +34 -26
- tomwer/core/process/test/test_axis.py +13 -12
- tomwer/core/process/test/test_dark_and_flat.py +10 -7
- tomwer/core/process/test/test_data_transfer.py +10 -8
- tomwer/core/process/test/test_nabu.py +14 -6
- tomwer/core/process/test/test_normalization.py +4 -4
- tomwer/core/scan/blissscan.py +3 -3
- tomwer/core/scan/edfscan.py +13 -10
- tomwer/core/scan/hdf5scan.py +19 -530
- tomwer/core/scan/nxtomoscan.py +534 -0
- tomwer/core/scan/scanbase.py +72 -44
- tomwer/core/scan/scanfactory.py +13 -13
- tomwer/core/scan/test/test_edf.py +2 -2
- tomwer/core/scan/test/test_future_scan.py +3 -3
- tomwer/core/scan/test/test_h5.py +18 -16
- tomwer/core/scan/test/test_process_registration.py +4 -40
- tomwer/core/scan/test/test_scan.py +5 -78
- tomwer/core/settings.py +22 -2
- tomwer/core/test/test_scanutils.py +8 -7
- tomwer/core/test/test_utils.py +35 -28
- tomwer/core/tomwer_object.py +1 -1
- tomwer/core/utils/__init__.py +0 -466
- tomwer/core/utils/deprecation.py +1 -1
- tomwer/core/utils/dictutils.py +14 -0
- tomwer/core/utils/lbsram.py +35 -0
- tomwer/core/utils/nxtomoutils.py +1 -1
- tomwer/core/utils/scanutils.py +6 -6
- tomwer/core/utils/spec.py +263 -0
- 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/core/volume/volumefactory.py +2 -2
- tomwer/gui/cluster/slurm.py +274 -65
- tomwer/gui/cluster/supervisor.py +12 -0
- tomwer/gui/cluster/test/test_cluster.py +14 -2
- tomwer/gui/cluster/test/test_supervisor.py +3 -3
- tomwer/gui/configuration/__init__.py +0 -0
- tomwer/gui/{reconstruction/nabu → configuration}/action.py +1 -32
- tomwer/gui/configuration/level.py +22 -0
- tomwer/gui/control/actions.py +54 -0
- tomwer/gui/control/datalist.py +83 -16
- tomwer/gui/control/datalistener.py +4 -16
- tomwer/gui/control/datawatcher/controlwidget.py +2 -4
- tomwer/gui/control/datawatcher/datawatcher.py +1 -24
- tomwer/gui/control/{email.py → emailnotifier.py} +9 -18
- tomwer/gui/control/history.py +2 -2
- tomwer/gui/control/observations.py +2 -2
- tomwer/gui/control/reducedarkflatselector.py +9 -9
- tomwer/gui/control/selectorwidgetbase.py +36 -9
- tomwer/gui/control/serie/seriecreator.py +5 -22
- tomwer/gui/control/test/test_email.py +1 -1
- tomwer/gui/control/test/test_scanvalidator.py +6 -5
- tomwer/gui/control/test/test_single_tomo_obj.py +3 -3
- tomwer/gui/control/tomoobjdisplaymode.py +8 -0
- tomwer/gui/debugtools/datasetgenerator.py +3 -3
- tomwer/gui/edit/dkrfpatch.py +20 -26
- tomwer/gui/edit/imagekeyeditor.py +11 -12
- tomwer/gui/edit/nxtomoeditor.py +111 -44
- tomwer/gui/edit/nxtomowarmer.py +7 -6
- tomwer/gui/edit/test/test_dkrf_patch.py +13 -13
- tomwer/gui/edit/test/test_image_key_editor.py +3 -3
- tomwer/gui/edit/test/test_nx_editor.py +40 -16
- tomwer/gui/icat/__init__.py +0 -0
- tomwer/gui/icat/createscreenshots.py +80 -0
- tomwer/gui/icat/gallery.py +214 -0
- tomwer/gui/icat/publish.py +187 -0
- tomwer/gui/imagefromfile.py +2 -2
- tomwer/gui/qfolderdialog.py +24 -1
- tomwer/gui/reconstruction/axis/CompareImages.py +88 -168
- tomwer/gui/reconstruction/axis/axis.py +171 -57
- tomwer/gui/reconstruction/axis/radioaxis.py +122 -257
- tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +3 -2
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -1
- tomwer/gui/reconstruction/nabu/castvolume.py +14 -3
- tomwer/gui/reconstruction/nabu/check.py +9 -9
- tomwer/gui/reconstruction/nabu/helical.py +29 -12
- tomwer/gui/reconstruction/nabu/nabuconfig/base.py +2 -4
- tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +2 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/output.py +126 -35
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +39 -32
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +222 -31
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +57 -27
- tomwer/gui/reconstruction/nabu/nabuflow.py +12 -20
- tomwer/gui/reconstruction/nabu/slices.py +10 -11
- tomwer/gui/reconstruction/nabu/volume.py +22 -10
- tomwer/gui/reconstruction/normalization/intensity.py +18 -48
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +8 -24
- tomwer/gui/reconstruction/saaxis/dimensionwidget.py +1 -1
- tomwer/gui/reconstruction/saaxis/saaxis.py +9 -21
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +45 -12
- tomwer/gui/reconstruction/scores/control.py +2 -9
- tomwer/gui/reconstruction/scores/scoreplot.py +13 -11
- tomwer/gui/reconstruction/test/test_axis.py +41 -16
- tomwer/gui/reconstruction/test/test_nabu.py +31 -9
- tomwer/gui/reconstruction/test/test_saaxis.py +3 -3
- tomwer/gui/reconstruction/test/test_sadeltabeta.py +12 -2
- tomwer/gui/settings.py +5 -28
- tomwer/gui/stackplot.py +2 -5
- tomwer/gui/stitching/action.py +49 -0
- tomwer/gui/stitching/config/axisparams.py +7 -24
- tomwer/gui/stitching/config/output.py +10 -8
- tomwer/gui/stitching/config/positionoveraxis.py +22 -23
- tomwer/gui/stitching/normalization.py +117 -0
- tomwer/gui/stitching/stitchandbackground.py +4 -6
- tomwer/gui/stitching/stitching.py +267 -45
- tomwer/gui/stitching/stitching_preview.py +62 -55
- tomwer/gui/stitching/stitching_raw.py +13 -12
- tomwer/gui/stitching/z_stitching/fineestimation.py +0 -60
- tomwer/gui/utils/buttons.py +112 -29
- tomwer/gui/utils/inputwidget.py +43 -25
- tomwer/gui/utils/lineselector/lineselector.py +1 -1
- tomwer/gui/utils/scandescription.py +4 -0
- tomwer/gui/utils/step.py +144 -0
- tomwer/gui/utils/unitsystem.py +2 -5
- tomwer/gui/utils/vignettes.py +176 -15
- tomwer/gui/visualization/dataviewer.py +48 -35
- tomwer/gui/visualization/diffviewer/diffviewer.py +7 -16
- tomwer/gui/visualization/diffviewer/shiftwidget.py +2 -5
- tomwer/gui/visualization/scanoverview.py +1 -1
- tomwer/gui/visualization/sinogramviewer.py +20 -36
- tomwer/gui/visualization/test/test_diffviewer.py +3 -3
- tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +4 -4
- tomwer/gui/visualization/test/test_sinogramviewer.py +2 -2
- tomwer/gui/visualization/test/test_stacks.py +3 -3
- tomwer/gui/visualization/test/test_volumeviewer.py +65 -67
- tomwer/gui/visualization/volumeviewer.py +114 -113
- tomwer/io/utils/h5pyutils.py +3 -3
- tomwer/io/utils/raw_and_processed_data.py +84 -0
- tomwer/io/utils/tomoobj.py +4 -6
- tomwer/io/utils/utils.py +7 -7
- tomwer/resources/gui/icons/parameters.svg +1 -1
- tomwer/resources/gui/icons/ruler.png +0 -0
- tomwer/resources/gui/icons/ruler.svg +273 -0
- tomwer/resources/gui/icons/short_description.png +0 -0
- tomwer/resources/gui/icons/short_description.svg +58 -0
- tomwer/resources/gui/icons/url.png +0 -0
- tomwer/resources/gui/icons/url.svg +58 -0
- tomwer/resources/gui/illustrations/no_rot.svg +1 -1
- tomwer/synctools/stacks/edit/darkflatpatch.py +19 -14
- tomwer/synctools/stacks/edit/imagekeyeditor.py +2 -2
- tomwer/synctools/stacks/reconstruction/axis.py +4 -4
- tomwer/synctools/stacks/reconstruction/castvolume.py +22 -7
- tomwer/synctools/stacks/reconstruction/dkrefcopy.py +25 -20
- tomwer/synctools/stacks/reconstruction/nabu.py +2 -2
- tomwer/synctools/stacks/reconstruction/normalization.py +2 -2
- tomwer/synctools/stacks/reconstruction/saaxis.py +2 -2
- tomwer/synctools/stacks/reconstruction/sadeltabeta.py +2 -2
- tomwer/synctools/test/test_darkRefs.py +7 -58
- tomwer/synctools/test/test_foldertransfer.py +6 -6
- tomwer/synctools/utils/scanstages.py +6 -6
- tomwer/tests/conftest.py +34 -0
- tomwer/tests/datasets.py +13 -0
- tomwer/tests/test_scripts.py +91 -41
- tomwer/tests/utils.py +5 -0
- tomwer/third_part/WaitingOverlay.py +110 -0
- tomwer/third_part/__init__.py +0 -0
- tomwer/version.py +2 -2
- tomwer-1.3.12-py3.11-nspkg.pth +1 -0
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/METADATA +73 -58
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/RECORD +287 -286
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.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 -760
- tomwer/gui/reconstruction/test/test_lamino.py +0 -189
- tomwer/resources/gui/icons/esrf_1.svg +0 -307
- tomwer/resources/gui/icons/lamino_parameters.svg +0 -70
- tomwer/resources/gui/icons/triangle.svg +0 -80
- 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/synctools/test/test_scanstages.py +0 -162
- tomwer/tests/utils/__init__.py +0 -247
- tomwer/tests/utils/utilstest.py +0 -220
- tomwer-1.2.1-py3.11-nspkg.pth +0 -1
- /tomwer/core/process/control/{email.py → emailnotifier.py} +0 -0
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/LICENSE +0 -0
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/entry_points.txt +0 -0
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.2.1.dist-info → tomwer-1.3.12.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@ from typing import Union
|
|
4
4
|
import numpy
|
5
5
|
from nabu.stitching.frame_composition import ZFrameComposition
|
6
6
|
from silx.gui import qt
|
7
|
+
from tomwer.gui.utils.buttons import TapeMeasureToolButton
|
7
8
|
from tomoscan.esrf.scan.utils import get_data
|
8
9
|
from tomoscan.identifier import BaseIdentifier
|
9
10
|
from tomoscan.scanbase import TomoScanBase
|
@@ -14,27 +15,61 @@ from tomwer.gui import icons as tomwer_icons
|
|
14
15
|
from tomwer.gui import settings
|
15
16
|
from tomwer.gui.stitching.stitchandbackground import StitchAndBackgroundAlphaMixIn
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
PlotWithWaitingLabel as _PlotWithWaitingLabel,
|
20
|
-
)
|
21
|
-
except ImportError:
|
22
|
-
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
|
23
20
|
|
24
21
|
_logger = logging.getLogger(__name__)
|
25
22
|
|
26
23
|
|
27
|
-
class
|
24
|
+
class _PreviewPlot2D(Plot2D):
|
25
|
+
"""simple inheritance to get data from the 'stitched image' instead of the 'background / overlay' image"""
|
26
|
+
|
27
|
+
def _getImageValue(self, x, y):
|
28
|
+
pickedMask = None
|
29
|
+
for picked in self.pickItems(
|
30
|
+
*self.dataToPixel(x, y, check=False),
|
31
|
+
lambda item: isinstance(item, items.ImageBase),
|
32
|
+
):
|
33
|
+
if isinstance(picked.getItem(), items.MaskImageData):
|
34
|
+
if pickedMask is None: # Use top-most if many masks
|
35
|
+
pickedMask = picked
|
36
|
+
else:
|
37
|
+
# we want to avoid displaying the value of the background image. So just ignore it.
|
38
|
+
# TODO: see with Thomas if there is a better way to do this.
|
39
|
+
# like starting by the active image ?
|
40
|
+
image = picked.getItem()
|
41
|
+
if image.getLegend() == StitchAndBackgroundAlphaMixIn.LEGEND_BACKGROUND:
|
42
|
+
continue
|
43
|
+
|
44
|
+
indices = picked.getIndices(copy=False)
|
45
|
+
if indices is not None:
|
46
|
+
row, col = indices[0][0], indices[1][0]
|
47
|
+
value = image.getData(copy=False)[row, col]
|
48
|
+
|
49
|
+
if pickedMask is not None: # Check if masked
|
50
|
+
maskItem = pickedMask.getItem()
|
51
|
+
indices = pickedMask.getIndices()
|
52
|
+
row, col = indices[0][0], indices[1][0]
|
53
|
+
if maskItem.getData(copy=False)[row, col] != 0:
|
54
|
+
return value, "Masked"
|
55
|
+
return value
|
56
|
+
|
57
|
+
return "-" # No image picked
|
58
|
+
|
59
|
+
|
60
|
+
class PreviewStitchingPlot(Plot2D, StitchAndBackgroundAlphaMixIn):
|
28
61
|
DEFAULT_STITCHED_IMG_ALPHA = 0.95
|
29
|
-
DEFAULT_BACKGROUND_IMG_ALPHA = 0.
|
62
|
+
DEFAULT_BACKGROUND_IMG_ALPHA = 0.20
|
30
63
|
|
31
64
|
def __init__(self, parent=None) -> None:
|
32
65
|
super().__init__(parent=parent) # pylint: disable=E1123
|
66
|
+
self._waitingOverlay = WaitingOverlay(self)
|
67
|
+
self._waitingOverlay.setIconSize(qt.QSize(30, 30))
|
33
68
|
self._stitched_image = None
|
34
69
|
self._composition_background = None
|
35
70
|
|
36
71
|
# tune plot
|
37
|
-
self.
|
72
|
+
self.setYAxisInverted(settings.Y_AXIS_DOWNWARD)
|
38
73
|
# by default we want to have a full screen display
|
39
74
|
self.setAxesDisplayed(False)
|
40
75
|
|
@@ -47,6 +82,11 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
47
82
|
self.setKeepDataAspectRatio(True)
|
48
83
|
self.getColorBarWidget().hide()
|
49
84
|
|
85
|
+
# tape mesure action
|
86
|
+
self._tapeMeasureButton = TapeMeasureToolButton(parent=self, plot=self)
|
87
|
+
self._tapeMeasureButton.setCheckable(True)
|
88
|
+
self.toolBar().addWidget(self._tapeMeasureButton)
|
89
|
+
|
50
90
|
# removing some plot action to clear toolbar
|
51
91
|
self.getMaskAction().setVisible(False)
|
52
92
|
self.getCopyAction().setVisible(False)
|
@@ -62,7 +102,7 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
62
102
|
# set up
|
63
103
|
self.setAlphaBackgroundImg(value=self.DEFAULT_BACKGROUND_IMG_ALPHA)
|
64
104
|
self.setAlphaStitchedImg(value=self.DEFAULT_STITCHED_IMG_ALPHA)
|
65
|
-
self.
|
105
|
+
self._waitingOverlay.hide()
|
66
106
|
|
67
107
|
# connect signal / slot
|
68
108
|
self._backGroundAction.toggled.connect(self._update)
|
@@ -111,15 +151,19 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
111
151
|
shape=(
|
112
152
|
(raw_compositon.global_end_y[-1] - raw_compositon.global_start_y[0]),
|
113
153
|
frame_width,
|
154
|
+
4,
|
114
155
|
),
|
115
156
|
)
|
116
|
-
assert background.ndim ==
|
157
|
+
assert background.ndim == 3
|
117
158
|
|
118
159
|
def get_next_color():
|
160
|
+
yellow = qt.QColor(qt.Qt.yellow)
|
161
|
+
magenta = qt.QColor(qt.Qt.magenta)
|
162
|
+
blue = qt.QColor(qt.Qt.blue)
|
119
163
|
while True:
|
120
|
-
yield
|
121
|
-
yield
|
122
|
-
yield
|
164
|
+
yield yellow.red(), yellow.green(), yellow.blue(), 255
|
165
|
+
yield magenta.red(), magenta.green(), magenta.blue(), 255
|
166
|
+
yield blue.red(), blue.green(), blue.blue(), 255
|
123
167
|
|
124
168
|
colors_raw_frames = []
|
125
169
|
for _, color in zip(raw_compositon.local_end_y, get_next_color()):
|
@@ -127,6 +171,7 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
127
171
|
shape=(
|
128
172
|
raw_compositon.global_end_y[-1] - raw_compositon.global_start_y[0],
|
129
173
|
frame_width,
|
174
|
+
4,
|
130
175
|
),
|
131
176
|
fill_value=color,
|
132
177
|
)
|
@@ -196,44 +241,6 @@ class PreviewStitchingPlot(_PlotWithWaitingLabel, StitchAndBackgroundAlphaMixIn)
|
|
196
241
|
def stitched_image(self):
|
197
242
|
return self._stitched_image
|
198
243
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
def addImage(self, *args, **kwargs):
|
204
|
-
self.getPlotWidget().addImage(*args, **kwargs)
|
205
|
-
|
206
|
-
def removeImage(self, *args, **kwargs):
|
207
|
-
self.getPlotWidget().removeImage(*args, **kwargs)
|
208
|
-
|
209
|
-
def toolBar(self, *args, **kwargs):
|
210
|
-
return self.getPlotWidget().toolBar(*args, **kwargs)
|
211
|
-
|
212
|
-
def setKeepDataAspectRatio(self, *args, **kwargs):
|
213
|
-
return self.getPlotWidget().setKeepDataAspectRatio(*args, **kwargs)
|
214
|
-
|
215
|
-
def getColorBarWidget(self, *args, **kwargs):
|
216
|
-
return self.getPlotWidget().getColorBarWidget(*args, **kwargs)
|
217
|
-
|
218
|
-
def getMaskAction(self, *args, **kwargs):
|
219
|
-
return self.getPlotWidget().getMaskAction(*args, **kwargs)
|
220
|
-
|
221
|
-
def getCopyAction(self, *args, **kwargs):
|
222
|
-
return self.getPlotWidget().getCopyAction(*args, **kwargs)
|
223
|
-
|
224
|
-
def addToolBar(self, *args, **kwargs):
|
225
|
-
return self.getPlotWidget().addToolBar(*args, **kwargs)
|
226
|
-
|
227
|
-
def setActiveImage(self, *args, **kwargs):
|
228
|
-
return self.getPlotWidget().setActiveImage(*args, **kwargs)
|
229
|
-
|
230
|
-
def setAxesDisplayed(self, *args, **kwargs):
|
231
|
-
plotWidget = self.getPlotWidget()
|
232
|
-
if hasattr(plotWidget, "setAxesDisplayed"):
|
233
|
-
plotWidget.setAxesDisplayed(*args, **kwargs)
|
234
|
-
|
235
|
-
def getDefaultColormap(self, *args, **kwargs):
|
236
|
-
return self.getPlotWidget().getDefaultColormap()
|
237
|
-
|
238
|
-
def setDefaultColormap(self, *args, **kwargs):
|
239
|
-
return self.getPlotWidget().setDefaultColormap(*args, **kwargs)
|
244
|
+
def setPixelSize(self, pixel_size: Union[tuple, float]):
|
245
|
+
"""set the pixel size to be used by the ruler"""
|
246
|
+
self._tapeMeasureButton.setPixelSize(pixel_size_m=pixel_size)
|
@@ -6,7 +6,7 @@ from contextlib import AbstractContextManager
|
|
6
6
|
|
7
7
|
from silx.gui import qt
|
8
8
|
from silx.gui.plot import PlotWindow
|
9
|
-
from
|
9
|
+
from nxtomo.nxobject.nxdetector import ImageKey
|
10
10
|
from tomwer.core.volume.volumebase import TomwerVolumeBase
|
11
11
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
12
12
|
from tomwer.core.tomwer_object import TomwerObject
|
@@ -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()
|
@@ -322,22 +322,26 @@ class RawStitchingPlot(PlotWindow):
|
|
322
322
|
# compute flat field
|
323
323
|
# TODO: this must be done in another thread... but sync with update might be difficult...
|
324
324
|
try:
|
325
|
-
reduced_darks = scan.load_reduced_darks(
|
325
|
+
reduced_darks, reduced_darks_infos = scan.load_reduced_darks(
|
326
|
+
return_info=True
|
327
|
+
)
|
326
328
|
except Exception:
|
327
329
|
_logger.warning(
|
328
330
|
f"no reduced dark found for {scan}. Please compute them to get a better display."
|
329
331
|
)
|
330
332
|
else:
|
331
|
-
scan.set_reduced_darks(reduced_darks)
|
333
|
+
scan.set_reduced_darks(reduced_darks, darks_infos=reduced_darks_infos)
|
332
334
|
|
333
335
|
try:
|
334
|
-
reduced_flats = scan.load_reduced_flats(
|
336
|
+
reduced_flats, reduced_flats_info = scan.load_reduced_flats(
|
337
|
+
return_info=True
|
338
|
+
)
|
335
339
|
except Exception:
|
336
340
|
_logger.warning(
|
337
341
|
f"no reduced flat(s) found for {scan}. Please compute them to get a better display."
|
338
342
|
)
|
339
343
|
else:
|
340
|
-
scan.set_reduced_flats(reduced_flats)
|
344
|
+
scan.set_reduced_flats(reduced_flats, flats_infos=reduced_flats_info)
|
341
345
|
|
342
346
|
reading_order_ref = self._getReadingOrderRef()
|
343
347
|
reading_order = self._scan_reading_order[scan.get_identifier().to_str()]
|
@@ -557,10 +561,7 @@ class AlphaValueSlider(qt.QTableWidget):
|
|
557
561
|
self._visibleButton.released.connect(self._setVisible)
|
558
562
|
|
559
563
|
# expose API
|
560
|
-
self._slider.valueChanged.connect(self.
|
561
|
-
|
562
|
-
def _changed(self, value: int):
|
563
|
-
self.valueChanged.emit(value)
|
564
|
+
self._slider.valueChanged.connect(self.valueChanged)
|
564
565
|
|
565
566
|
def _setInvisible(self, *args, **kwargs):
|
566
567
|
self._slider.setValue(0)
|
@@ -10,7 +10,6 @@ from typing import Union
|
|
10
10
|
from nabu.stitching import config as _nabu_stitching_config
|
11
11
|
from nabu.stitching.config import StitchingType
|
12
12
|
from nabu.stitching.overlap import OverlapStitchingStrategy
|
13
|
-
from nabu.stitching.utils import ScoreMethod as _NabuScoreMethod
|
14
13
|
from nabu.stitching.utils import ShiftAlgorithm as _NabuShiftAlgorithm
|
15
14
|
from silx.gui import qt
|
16
15
|
from tomoscan.serie import Serie
|
@@ -39,44 +38,8 @@ class Axis_N_Params(qt.QGroupBox):
|
|
39
38
|
)
|
40
39
|
self.layout().addRow("image registration method", self._imageRegMethodCB)
|
41
40
|
|
42
|
-
# window size
|
43
|
-
self._windowSize = qt.QSpinBox(self)
|
44
|
-
self._windowSizeLabel = qt.QLabel(
|
45
|
-
_nabu_stitching_config.KEY_WINDOW_SIZE.replace("_", " "), self
|
46
|
-
)
|
47
|
-
self.layout().addRow(self._windowSizeLabel, self._windowSize)
|
48
|
-
self._windowSize.setToolTip("research window width to find shifts")
|
49
|
-
|
50
|
-
# score method
|
51
|
-
self._scoreCB = qt.QComboBox(self)
|
52
|
-
for score_method in _NabuScoreMethod.values():
|
53
|
-
self._scoreCB.addItem(score_method)
|
54
|
-
self._scoreCBLabel = qt.QLabel(
|
55
|
-
_nabu_stitching_config.KEY_SCORE_METHOD.replace("_", " "), self
|
56
|
-
)
|
57
|
-
self.layout().addRow(self._scoreCBLabel, self._scoreCB)
|
58
|
-
self._windowSize.setToolTip(
|
59
|
-
"method to use in order to compute score and determine the best shift"
|
60
|
-
)
|
61
|
-
|
62
|
-
# connect signal / slot
|
63
|
-
self._imageRegMethodCB.currentTextChanged.connect(self._updatePossibleOpts)
|
64
|
-
|
65
41
|
# set up
|
66
42
|
self._imageRegMethodCB.setCurrentText(_NabuShiftAlgorithm.NONE.value)
|
67
|
-
self._updatePossibleOpts()
|
68
|
-
|
69
|
-
def getWindowSize(self):
|
70
|
-
return self._windowSize.value()
|
71
|
-
|
72
|
-
def setWindowSize(self, window_size):
|
73
|
-
return self._windowSize.setValue(int(window_size))
|
74
|
-
|
75
|
-
def getScoreMethod(self):
|
76
|
-
return _NabuScoreMethod.from_value(self._scoreCB.currentText())
|
77
|
-
|
78
|
-
def setScoreMethod(self, method):
|
79
|
-
self._scoreCB.setCurrentText(_NabuScoreMethod.from_value(method).value)
|
80
43
|
|
81
44
|
def getCurrentMethod(self):
|
82
45
|
return _NabuShiftAlgorithm.from_value(self._imageRegMethodCB.currentText())
|
@@ -89,13 +52,6 @@ class Axis_N_Params(qt.QGroupBox):
|
|
89
52
|
def getOptsLine(self) -> str:
|
90
53
|
current_method = self.getCurrentMethod()
|
91
54
|
line_ = f"{_nabu_stitching_config.KEY_IMG_REG_METHOD}={current_method.value}"
|
92
|
-
if current_method is _NabuShiftAlgorithm.SHIFT_GRID:
|
93
|
-
line_ = ",".join(
|
94
|
-
(
|
95
|
-
line_,
|
96
|
-
f"{_nabu_stitching_config.KEY_WINDOW_SIZE}={self.getWindowSize()},{_nabu_stitching_config.KEY_SCORE_METHOD}={self.getScoreMethod().value}",
|
97
|
-
)
|
98
|
-
)
|
99
55
|
return line_
|
100
56
|
|
101
57
|
def setOptsLine(self, opt_line: str) -> None:
|
@@ -113,13 +69,6 @@ class Axis_N_Params(qt.QGroupBox):
|
|
113
69
|
except Exception as e:
|
114
70
|
_logger.error(e)
|
115
71
|
|
116
|
-
score_method = opts.get(_nabu_stitching_config.KEY_SCORE_METHOD, None)
|
117
|
-
if score_method is not None:
|
118
|
-
try:
|
119
|
-
self.setScoreMethod(score_method)
|
120
|
-
except Exception as e:
|
121
|
-
_logger.error(e)
|
122
|
-
|
123
72
|
img_reg_exp_method = opts.get(_nabu_stitching_config.KEY_IMG_REG_METHOD, None)
|
124
73
|
if img_reg_exp_method is not None:
|
125
74
|
try:
|
@@ -127,15 +76,6 @@ class Axis_N_Params(qt.QGroupBox):
|
|
127
76
|
except Exception as e:
|
128
77
|
_logger.error(e)
|
129
78
|
|
130
|
-
def _updatePossibleOpts(self, *args, **kwargs):
|
131
|
-
current_method = self.getCurrentMethod()
|
132
|
-
self._windowSizeLabel.setVisible(
|
133
|
-
current_method is _NabuShiftAlgorithm.SHIFT_GRID
|
134
|
-
)
|
135
|
-
self._windowSize.setVisible(current_method is _NabuShiftAlgorithm.SHIFT_GRID)
|
136
|
-
self._scoreCBLabel.setVisible(current_method is _NabuShiftAlgorithm.SHIFT_GRID)
|
137
|
-
self._scoreCB.setVisible(current_method is _NabuShiftAlgorithm.SHIFT_GRID)
|
138
|
-
|
139
79
|
|
140
80
|
class AutoRefineWidget(qt.QWidget):
|
141
81
|
"""
|
tomwer/gui/utils/buttons.py
CHANGED
@@ -1,39 +1,20 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# /*##########################################################################
|
3
|
-
# Copyright (C) 2017 European Synchrotron Radiation Facility
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
# THE SOFTWARE.
|
22
|
-
#
|
23
|
-
#############################################################################*/
|
24
|
-
|
25
1
|
"""
|
26
2
|
Button of general usage.
|
27
3
|
"""
|
28
4
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
5
|
+
import numpy
|
6
|
+
import logging
|
7
|
+
from typing import Optional, Union
|
34
8
|
from silx.gui import qt
|
9
|
+
from silx.gui.plot.tools.roi import RegionOfInterestManager
|
10
|
+
from silx.gui.plot.items.roi import LineROI
|
11
|
+
from silx.gui.plot.PlotToolButtons import PlotToolButton
|
35
12
|
|
36
13
|
from tomwer.gui import icons
|
14
|
+
from pyunitsystem.metricsystem import MetricSystem
|
15
|
+
|
16
|
+
|
17
|
+
_logger = logging.getLogger(__file__)
|
37
18
|
|
38
19
|
|
39
20
|
class PadlockButton(qt.QPushButton):
|
@@ -100,3 +81,105 @@ class TabBrowsersButtons(qt.QWidget):
|
|
100
81
|
|
101
82
|
def _nextReleased(self, *args, **kwargs):
|
102
83
|
self.sigNextReleased.emit()
|
84
|
+
|
85
|
+
|
86
|
+
class TapeMeasureToolButton(PlotToolButton):
|
87
|
+
"""Button to active measurement between two point of the plot"""
|
88
|
+
|
89
|
+
class TapeMeasureROI(LineROI):
|
90
|
+
def __init__(self, parent=None, pixel_size_m=None):
|
91
|
+
super().__init__(parent)
|
92
|
+
self._pixel_size_m = None
|
93
|
+
self.setPixelSize(pixel_size_m)
|
94
|
+
|
95
|
+
def setEndPoints(self, startPoint, endPoint):
|
96
|
+
distance_px = numpy.linalg.norm(endPoint - startPoint)
|
97
|
+
super().setEndPoints(startPoint=startPoint, endPoint=endPoint)
|
98
|
+
if self._pixel_size_m is None:
|
99
|
+
self._updateText(f"{distance_px :.1f}px")
|
100
|
+
else:
|
101
|
+
distance_m = distance_px * self._pixel_size_m
|
102
|
+
value, unit = MetricSystem.cast_metric_to_best_unit(distance_m)
|
103
|
+
self._updateText(f"{distance_px :.1f}px ({value:.2f}{unit})")
|
104
|
+
|
105
|
+
def setPixelSize(self, pixel_size_m: Optional[Union[tuple, float]]):
|
106
|
+
if isinstance(pixel_size_m, (tuple, list)):
|
107
|
+
assert (
|
108
|
+
len(pixel_size_m) == 2
|
109
|
+
), "expects at most two pixel size values (x and y values)"
|
110
|
+
if not numpy.isclose(pixel_size_m[0], pixel_size_m[1]):
|
111
|
+
value, unit = MetricSystem.cast_metric_to_best_unit(pixel_size_m[0])
|
112
|
+
_logger.warning(
|
113
|
+
f"TapeMeasure is only handling square pixels for now. Will consider the pixel is {value:.2f}{unit}x{value:.2f}{unit}"
|
114
|
+
)
|
115
|
+
pixel_size_m = pixel_size_m[0]
|
116
|
+
self._pixel_size_m = pixel_size_m
|
117
|
+
|
118
|
+
def __init__(self, parent=None, plot=None, pixel_size_mm=None):
|
119
|
+
super().__init__(parent=parent, plot=plot)
|
120
|
+
self._roiManager = None
|
121
|
+
self._lastRoiCreated = None
|
122
|
+
self._pixel_sixel_m = pixel_size_mm
|
123
|
+
self.setIcon(icons.getQIcon("ruler"))
|
124
|
+
self.setToolTip("measure distance between two pixels")
|
125
|
+
self.toggled.connect(self._callback)
|
126
|
+
self._connectPlot(plot)
|
127
|
+
|
128
|
+
def setPlot(self, plot):
|
129
|
+
return super().setPlot(plot)
|
130
|
+
|
131
|
+
def setPixelSize(self, pixel_size_m: Optional[Union[tuple, float]]):
|
132
|
+
self._pixel_sixel_m = pixel_size_m
|
133
|
+
|
134
|
+
def _callback(self, toggled):
|
135
|
+
if not self._roiManager:
|
136
|
+
return
|
137
|
+
if self._lastRoiCreated is not None:
|
138
|
+
self._lastRoiCreated.setVisible(self.isChecked())
|
139
|
+
if self.isChecked():
|
140
|
+
self._roiManager.start(
|
141
|
+
self.TapeMeasureROI,
|
142
|
+
self,
|
143
|
+
)
|
144
|
+
self.__interactiveModeStarted(self._roiManager)
|
145
|
+
else:
|
146
|
+
source = self._roiManager.getInteractionSource()
|
147
|
+
if source is self:
|
148
|
+
self._roiManager.stop()
|
149
|
+
|
150
|
+
def __interactiveModeStarted(self, roiManager):
|
151
|
+
roiManager.sigInteractiveModeFinished.connect(self.__interactiveModeFinished)
|
152
|
+
|
153
|
+
def __interactiveModeFinished(self):
|
154
|
+
roiManager = self._roiManager
|
155
|
+
if roiManager is not None:
|
156
|
+
roiManager.sigInteractiveModeFinished.disconnect(
|
157
|
+
self.__interactiveModeFinished
|
158
|
+
)
|
159
|
+
self.setChecked(False)
|
160
|
+
|
161
|
+
def _connectPlot(self, plot):
|
162
|
+
"""
|
163
|
+
Called when the plot is connected to the widget
|
164
|
+
:param plot: :class:`.PlotWidget` instance
|
165
|
+
"""
|
166
|
+
if plot is None:
|
167
|
+
return
|
168
|
+
self._roiManager = RegionOfInterestManager(plot)
|
169
|
+
self._roiManager.setColor("yellow") # Set the color of ROI
|
170
|
+
self._roiManager.sigRoiAdded.connect(self._registerCurrentROI)
|
171
|
+
|
172
|
+
def _disconnectPlot(self, plot):
|
173
|
+
if plot and self._lastRoiCreated is not None:
|
174
|
+
self._roiManager.removeRoi(self._lastRoiCreated)
|
175
|
+
self._lastRoiCreated = None
|
176
|
+
return super()._disconnectPlot(plot)
|
177
|
+
|
178
|
+
def _registerCurrentROI(self, currentRoi):
|
179
|
+
if self._lastRoiCreated is None:
|
180
|
+
self._lastRoiCreated = currentRoi
|
181
|
+
self._lastRoiCreated.setPixelSize(self._pixel_sixel_m)
|
182
|
+
elif currentRoi != self._lastRoiCreated and self._roiManager is not None:
|
183
|
+
self._roiManager.removeRoi(self._lastRoiCreated)
|
184
|
+
self._lastRoiCreated = currentRoi
|
185
|
+
self._lastRoiCreated.setPixelSize(self._pixel_sixel_m)
|
tomwer/gui/utils/inputwidget.py
CHANGED
@@ -28,7 +28,7 @@ __date__ = "16/08/2018"
|
|
28
28
|
|
29
29
|
import logging
|
30
30
|
import os
|
31
|
-
from typing import Optional
|
31
|
+
from typing import Optional, Union
|
32
32
|
|
33
33
|
import numpy
|
34
34
|
from nxtomomill.io.config import TomoEDFConfig as EDFConfig
|
@@ -41,7 +41,7 @@ from tomwer.gui import icons
|
|
41
41
|
from tomwer.gui.qlefilesystem import QLFileSystem
|
42
42
|
from tomwer.io.utils import get_default_directory
|
43
43
|
from tomwer.core.volume.volumefactory import VolumeFactory
|
44
|
-
from tomwer.core.process.
|
44
|
+
from tomwer.core.process.output import ProcessDataOutputDirMode
|
45
45
|
|
46
46
|
from tomwer.core.volume import (
|
47
47
|
EDFVolume,
|
@@ -271,42 +271,49 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
271
271
|
self.__buttonGroup.setExclusive(True)
|
272
272
|
|
273
273
|
tooltip = """Define the output directory of the nexus (.nx) file. Options are:
|
274
|
-
\n -
|
274
|
+
\n - same folder as scan: create the NXtomos at the same level as the bliss input file or spec folder
|
275
|
+
\n - 'RAW_DATA' folder: create NXtomos on the default 'RAW_DATA' folder (bliss default folder, nearby the 'raw' folder).
|
275
276
|
\n - 'PROCESSED_DATA' folder: create NXtomos on the default 'PROCESSED_DATA' folder (bliss default folder, nearby the 'raw' folder).
|
276
277
|
\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'
|
277
278
|
"""
|
278
279
|
|
279
280
|
# output dir is the folder containing the .nx file
|
280
|
-
self.
|
281
|
-
self.
|
282
|
-
self.layout().addWidget(self.
|
283
|
-
self.__buttonGroup.addButton(self.
|
281
|
+
self._inScanFolder = qt.QRadioButton("same folder as scan", self)
|
282
|
+
self._inScanFolder.setToolTip(tooltip)
|
283
|
+
self.layout().addWidget(self._inScanFolder, 0, 0, 1, 1)
|
284
|
+
self.__buttonGroup.addButton(self._inScanFolder)
|
284
285
|
# output dir is the default 'reduced'folder
|
285
286
|
self._processedDataFolderRB = qt.QRadioButton("'PROCESSED_DATA' folder", self)
|
286
287
|
self._processedDataFolderRB.setToolTip(tooltip)
|
287
288
|
self.layout().addWidget(self._processedDataFolderRB, 1, 0, 1, 1)
|
288
289
|
self.__buttonGroup.addButton(self._processedDataFolderRB)
|
290
|
+
# output dir is the default 'reduced'folder
|
291
|
+
self._rawDataFolderRB = qt.QRadioButton("'RAW_DATA' folder", self)
|
292
|
+
self._rawDataFolderRB.setToolTip(tooltip)
|
293
|
+
self.layout().addWidget(self._rawDataFolderRB, 2, 0, 1, 1)
|
294
|
+
self.__buttonGroup.addButton(self._rawDataFolderRB)
|
289
295
|
# manual
|
290
296
|
self._manualRB = qt.QRadioButton("custom output directory", self)
|
291
297
|
self._manualRB.setToolTip(tooltip)
|
292
|
-
self.layout().addWidget(self._manualRB,
|
298
|
+
self.layout().addWidget(self._manualRB, 3, 0, 1, 1)
|
293
299
|
self._outputFolderQLE = QLFileSystem("", self)
|
294
|
-
self.layout().addWidget(self._outputFolderQLE,
|
300
|
+
self.layout().addWidget(self._outputFolderQLE, 3, 1, 1, 1)
|
295
301
|
self._selectButton = qt.QPushButton("", self)
|
296
302
|
style = qt.QApplication.style()
|
297
303
|
icon_opendir = style.standardIcon(qt.QStyle.SP_DirOpenIcon)
|
298
304
|
self._selectButton.setIcon(icon_opendir)
|
299
305
|
self._selectButton.setToolTip("select output directory")
|
300
|
-
self.layout().addWidget(self._selectButton,
|
306
|
+
self.layout().addWidget(self._selectButton, 3, 2, 1, 1)
|
301
307
|
self.__buttonGroup.addButton(self._manualRB)
|
302
308
|
|
303
309
|
# connect signal / slot
|
304
310
|
self._selectButton.released.connect(self._selectOutpuFolder)
|
305
311
|
self.__buttonGroup.buttonReleased.connect(self._updateVisiblity)
|
306
|
-
self.
|
307
|
-
self._processedDataFolderRB.toggled.connect(self.
|
308
|
-
self.
|
309
|
-
self.
|
312
|
+
self._inScanFolder.toggled.connect(self.sigChanged)
|
313
|
+
self._processedDataFolderRB.toggled.connect(self.sigChanged)
|
314
|
+
self._rawDataFolderRB.toggled.connect(self.sigChanged)
|
315
|
+
self._manualRB.toggled.connect(self.sigChanged)
|
316
|
+
self._outputFolderQLE.editingFinished.connect(self.sigChanged)
|
310
317
|
|
311
318
|
# set up
|
312
319
|
self._processedDataFolderRB.setChecked(True)
|
@@ -316,9 +323,6 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
316
323
|
self._selectButton.setVisible(self._manualRB.isChecked())
|
317
324
|
self._outputFolderQLE.setVisible(self._manualRB.isChecked())
|
318
325
|
|
319
|
-
def _outputDirChanged(self):
|
320
|
-
self.sigChanged.emit()
|
321
|
-
|
322
326
|
def _selectOutpuFolder(self): # pragma: no cover
|
323
327
|
defaultDirectory = self._outputFolderQLE.text()
|
324
328
|
if os.path.isdir(defaultDirectory):
|
@@ -334,13 +338,15 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
334
338
|
self._outputFolderQLE.setText(dialog.selectedFiles()[0])
|
335
339
|
self.sigChanged.emit()
|
336
340
|
|
337
|
-
def getOutputFolder(self) -> str:
|
341
|
+
def getOutputFolder(self) -> Union[str, ProcessDataOutputDirMode]:
|
338
342
|
if self._manualRB.isChecked():
|
339
343
|
return self._outputFolderQLE.text()
|
340
344
|
elif self._processedDataFolderRB.isChecked():
|
341
|
-
return
|
342
|
-
elif self.
|
343
|
-
return
|
345
|
+
return ProcessDataOutputDirMode.PROCESSED_DATA_FOLDER
|
346
|
+
elif self._inScanFolder.isChecked():
|
347
|
+
return ProcessDataOutputDirMode.IN_SCAN_FOLDER
|
348
|
+
elif self._rawDataFolderRB.isChecked():
|
349
|
+
return ProcessDataOutputDirMode.RAW_DATA_FOLDER
|
344
350
|
else:
|
345
351
|
raise RuntimeError("Use case - h52nx output dir - not handled")
|
346
352
|
|
@@ -348,15 +354,17 @@ class NXTomomillOutputDirSelector(qt.QWidget):
|
|
348
354
|
old = self.blockSignals(True)
|
349
355
|
self._manualRB.setChecked(output_folder is not None)
|
350
356
|
try:
|
351
|
-
default_output =
|
357
|
+
default_output = ProcessDataOutputDirMode.from_value(output_folder)
|
352
358
|
except ValueError:
|
353
359
|
self._outputFolderQLE.setText(output_folder)
|
354
360
|
self._manualRB.setChecked(True)
|
355
361
|
else:
|
356
|
-
if default_output is
|
362
|
+
if default_output is ProcessDataOutputDirMode.IN_SCAN_FOLDER:
|
363
|
+
self._inScanFolder.setChecked(True)
|
364
|
+
elif default_output is ProcessDataOutputDirMode.PROCESSED_DATA_FOLDER:
|
357
365
|
self._processedDataFolderRB.setChecked(True)
|
358
|
-
elif default_output is
|
359
|
-
self.
|
366
|
+
elif default_output is ProcessDataOutputDirMode.RAW_DATA_FOLDER:
|
367
|
+
self._rawDataFolderRB.setChecked(True)
|
360
368
|
else:
|
361
369
|
raise ValueError(f"default output not handled ({default_output})")
|
362
370
|
finally:
|
@@ -516,6 +524,11 @@ class OutputVolumeDefinition(qt.QWidget):
|
|
516
524
|
os.environ["TOMWER_DEFAULT_INPUT_DIR"]
|
517
525
|
):
|
518
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
|
519
532
|
elif os.path.isdir("/data"):
|
520
533
|
dialog.setDirectory("/data")
|
521
534
|
|
@@ -532,6 +545,11 @@ class OutputVolumeDefinition(qt.QWidget):
|
|
532
545
|
os.environ["TOMWER_DEFAULT_INPUT_DIR"]
|
533
546
|
):
|
534
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
|
535
553
|
elif os.path.isdir("/data"):
|
536
554
|
dialog.setDirectory("/data")
|
537
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):
|
@@ -64,6 +64,10 @@ class ScanNameLabelAndShape(qt.QWidget):
|
|
64
64
|
def setScan(self, scan: Optional[TomwerScanBase]):
|
65
65
|
if scan is None or scan.path is None:
|
66
66
|
self.clear()
|
67
|
+
elif not isinstance(scan, TomwerScanBase):
|
68
|
+
raise TypeError(
|
69
|
+
f"Scan is expected to be an instance of {TomwerScanBase}. Get {type(scan)} instead"
|
70
|
+
)
|
67
71
|
else:
|
68
72
|
assert isinstance(scan, TomwerScanBase)
|
69
73
|
self._scanNameLabel.setText(scan.get_identifier().short_description())
|