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
@@ -37,11 +37,11 @@ from nxtomomill.utils import add_dark_flat_nx_file
|
|
37
37
|
from silx.gui import qt
|
38
38
|
from silx.gui.utils.testutils import TestCaseQt
|
39
39
|
from silx.io.url import DataUrl
|
40
|
-
from
|
40
|
+
from nxtomo.nxobject.nxdetector import ImageKey
|
41
41
|
from tomoscan.esrf.scan.utils import get_data
|
42
42
|
|
43
|
-
from tomwer.core.scan.
|
44
|
-
from tomwer.core.utils.scanutils import
|
43
|
+
from tomwer.core.scan.nxtomoscan import NXtomoScan
|
44
|
+
from tomwer.core.utils.scanutils import MockNXtomo
|
45
45
|
from tomwer.gui.edit.dkrfpatch import DarkRefPatchWidget, _DarkOrFlatUrl
|
46
46
|
from tomwer.tests.utils import skip_gui_test
|
47
47
|
|
@@ -62,13 +62,13 @@ class TestDarkOrFlatUrl(TestCaseQt):
|
|
62
62
|
)
|
63
63
|
self.output_folder = tempfile.mkdtemp()
|
64
64
|
#
|
65
|
-
hdf5_mock =
|
65
|
+
hdf5_mock = MockNXtomo(
|
66
66
|
scan_path=self.output_folder,
|
67
67
|
n_ini_proj=20,
|
68
68
|
n_proj=20,
|
69
69
|
create_ini_dark=True,
|
70
|
-
|
71
|
-
|
70
|
+
create_ini_flat=True,
|
71
|
+
create_final_flat=True,
|
72
72
|
)
|
73
73
|
self._scan = hdf5_mock.scan
|
74
74
|
self.scan_url = DataUrl(
|
@@ -130,23 +130,23 @@ class TestDarkRefPatchWidget(TestCaseQt):
|
|
130
130
|
self.output_folder1 = tempfile.mkdtemp()
|
131
131
|
self.output_folder2 = tempfile.mkdtemp()
|
132
132
|
|
133
|
-
hdf5_mock =
|
133
|
+
hdf5_mock = MockNXtomo(
|
134
134
|
scan_path=self.output_folder1,
|
135
135
|
n_ini_proj=20,
|
136
136
|
n_proj=20,
|
137
137
|
create_ini_dark=True,
|
138
|
-
|
139
|
-
|
138
|
+
create_ini_flat=True,
|
139
|
+
create_final_flat=True,
|
140
140
|
)
|
141
141
|
self._scanWithDarkAndRef = hdf5_mock.scan
|
142
142
|
|
143
|
-
hdf5_mock =
|
143
|
+
hdf5_mock = MockNXtomo(
|
144
144
|
scan_path=self.output_folder2,
|
145
145
|
n_ini_proj=20,
|
146
146
|
n_proj=20,
|
147
147
|
create_ini_dark=False,
|
148
|
-
|
149
|
-
|
148
|
+
create_ini_flat=False,
|
149
|
+
create_final_flat=False,
|
150
150
|
)
|
151
151
|
self._scan = hdf5_mock.scan
|
152
152
|
assert len(self._scan.darks) == 0
|
@@ -176,7 +176,7 @@ class TestDarkRefPatchWidget(TestCaseQt):
|
|
176
176
|
self.assertTrue(self._widget.getEndDarkUrl() is None)
|
177
177
|
self.assertTrue(self._widget.getEndFlatUrl() is None)
|
178
178
|
self.process()
|
179
|
-
new_scan =
|
179
|
+
new_scan = NXtomoScan(scan=self._scan.master_file, entry=self._scan.entry)
|
180
180
|
self.assertEqual(len(new_scan.darks), 1)
|
181
181
|
self.assertTrue(0 in new_scan.darks)
|
182
182
|
numpy.testing.assert_array_equal(
|
@@ -33,9 +33,9 @@ import tempfile
|
|
33
33
|
import pytest
|
34
34
|
from silx.gui import qt
|
35
35
|
from silx.gui.utils.testutils import SignalListener, TestCaseQt
|
36
|
-
from
|
36
|
+
from nxtomo.nxobject.nxdetector import ImageKey
|
37
37
|
|
38
|
-
from tomwer.core.utils.scanutils import
|
38
|
+
from tomwer.core.utils.scanutils import MockNXtomo
|
39
39
|
from tomwer.gui.edit.imagekeyeditor import (
|
40
40
|
ImageKeyDialog,
|
41
41
|
ImageKeyUpgraderWidget,
|
@@ -55,7 +55,7 @@ class TestImageKeyEditorGUI(TestCaseQt):
|
|
55
55
|
self._widget = ImageKeyDialog(parent=None)
|
56
56
|
self.output_folder = tempfile.mkdtemp()
|
57
57
|
|
58
|
-
hdf5_mock =
|
58
|
+
hdf5_mock = MockNXtomo(
|
59
59
|
scan_path=self.output_folder,
|
60
60
|
n_ini_proj=20,
|
61
61
|
n_proj=20,
|
@@ -2,21 +2,28 @@ import os
|
|
2
2
|
|
3
3
|
import numpy
|
4
4
|
import pytest
|
5
|
-
from nxtomomill.nexus.nxtomo import NXtomo
|
6
5
|
from silx.gui import qt
|
7
|
-
from tomoscan.esrf.scan.hdf5scan import ImageKey
|
8
|
-
from tomoscan.scanbase import _FOV
|
9
|
-
from tomoscan.unitsystem.energysystem import EnergySI
|
10
|
-
from tomoscan.unitsystem.metricsystem import MetricSystem
|
11
6
|
|
12
|
-
from
|
7
|
+
from pyunitsystem.energysystem import EnergySI
|
8
|
+
from pyunitsystem.metricsystem import MetricSystem
|
9
|
+
|
10
|
+
from nxtomo.application.nxtomo import NXtomo
|
11
|
+
from nxtomo.nxobject.nxdetector import ImageKey, FOV
|
12
|
+
from nxtomo.utils.transformation import (
|
13
|
+
build_matrix,
|
14
|
+
UDDetTransformation,
|
15
|
+
LRDetTransformation,
|
16
|
+
)
|
17
|
+
from nxtomo.nxobject.nxtransformations import NXtransformations
|
18
|
+
|
19
|
+
from tomwer.core.scan.nxtomoscan import NXtomoScan
|
13
20
|
from tomwer.gui.edit.nxtomoeditor import NXtomoEditor, _TranslationMetricEntry
|
14
21
|
from tomwer.tests.conftest import qtapp # noqa F401
|
15
22
|
|
16
23
|
|
17
24
|
@pytest.mark.parametrize("x_pixel_size", (None, 0.12))
|
18
25
|
@pytest.mark.parametrize("y_pixel_size", (None, 0.0065))
|
19
|
-
@pytest.mark.parametrize("field_of_view",
|
26
|
+
@pytest.mark.parametrize("field_of_view", FOV.values())
|
20
27
|
@pytest.mark.parametrize("distance", (None, 1.2))
|
21
28
|
@pytest.mark.parametrize("energy", (None, 23.5))
|
22
29
|
@pytest.mark.parametrize("x_flipped", (True, False))
|
@@ -42,14 +49,20 @@ def test_nx_editor(
|
|
42
49
|
nx_tomo.instrument.detector.y_pixel_size = y_pixel_size
|
43
50
|
nx_tomo.instrument.detector.field_of_view = field_of_view
|
44
51
|
nx_tomo.instrument.detector.distance = distance
|
45
|
-
nx_tomo.instrument.detector.x_flipped = x_flipped
|
46
|
-
nx_tomo.instrument.detector.y_flipped = y_flipped
|
47
52
|
nx_tomo.energy = energy
|
48
53
|
nx_tomo.sample.x_translation = x_translation
|
49
54
|
nx_tomo.sample.z_translation = z_translation
|
50
55
|
nx_tomo.instrument.detector.image_key_control = [ImageKey.PROJECTION.value] * 12
|
51
56
|
nx_tomo.instrument.detector.data = numpy.empty(shape=(12, 10, 10))
|
52
57
|
nx_tomo.sample.rotation_angle = numpy.linspace(0, 20, num=12)
|
58
|
+
if x_flipped:
|
59
|
+
nx_tomo.instrument.detector.transformations.add_transformation(
|
60
|
+
LRDetTransformation()
|
61
|
+
)
|
62
|
+
if y_flipped:
|
63
|
+
nx_tomo.instrument.detector.transformations.add_transformation(
|
64
|
+
UDDetTransformation()
|
65
|
+
)
|
53
66
|
|
54
67
|
file_path = os.path.join(tmp_path, "nxtomo.nx")
|
55
68
|
entry = "entry0000"
|
@@ -58,7 +71,7 @@ def test_nx_editor(
|
|
58
71
|
data_path=entry,
|
59
72
|
)
|
60
73
|
|
61
|
-
scan =
|
74
|
+
scan = NXtomoScan(file_path, entry)
|
62
75
|
|
63
76
|
# 2.0 create the widget and do the edition
|
64
77
|
widget = NXtomoEditor()
|
@@ -107,7 +120,7 @@ def test_nx_editor(
|
|
107
120
|
widget._xPixelSizeMetricEntry.setUnit("nm")
|
108
121
|
widget._yPixelSizeMetricEntry.setValue(2.1e-7)
|
109
122
|
widget._distanceMetricEntry.setValue("unknown")
|
110
|
-
widget._fieldOfViewCB.setCurrentText(
|
123
|
+
widget._fieldOfViewCB.setCurrentText(FOV.HALF.value)
|
111
124
|
widget._xFlippedCB.setChecked(not x_flipped)
|
112
125
|
widget._xTranslationQLE.setValue(1.8)
|
113
126
|
widget._xTranslationQLE.setUnit("mm")
|
@@ -135,10 +148,21 @@ def test_nx_editor(
|
|
135
148
|
assert overwrite_nx_tomo.instrument.detector.y_pixel_size.value == 2.1e-7
|
136
149
|
|
137
150
|
assert overwrite_nx_tomo.instrument.detector.distance.value is None
|
138
|
-
assert overwrite_nx_tomo.instrument.detector.field_of_view is
|
151
|
+
assert overwrite_nx_tomo.instrument.detector.field_of_view is FOV.HALF
|
139
152
|
|
140
|
-
|
141
|
-
|
153
|
+
final_transformation = NXtransformations()
|
154
|
+
|
155
|
+
if y_flipped:
|
156
|
+
final_transformation.add_transformation(UDDetTransformation())
|
157
|
+
if not x_flipped: # as we invert _xFlippedCB combobox
|
158
|
+
final_transformation.add_transformation(LRDetTransformation())
|
159
|
+
|
160
|
+
numpy.testing.assert_allclose(
|
161
|
+
build_matrix(
|
162
|
+
overwrite_nx_tomo.instrument.detector.transformations.transformations
|
163
|
+
),
|
164
|
+
build_matrix(final_transformation.transformations),
|
165
|
+
)
|
142
166
|
|
143
167
|
numpy.testing.assert_array_almost_equal(
|
144
168
|
overwrite_nx_tomo.sample.x_translation.value,
|
@@ -181,7 +205,7 @@ def test_nx_editor_lock(
|
|
181
205
|
data_path=entry,
|
182
206
|
)
|
183
207
|
|
184
|
-
scan_1 =
|
208
|
+
scan_1 = NXtomoScan(file_path, entry)
|
185
209
|
|
186
210
|
nx_tomo_2 = NXtomo()
|
187
211
|
nx_tomo_2.instrument.detector.x_pixel_size = 4.023
|
@@ -206,7 +230,7 @@ def test_nx_editor_lock(
|
|
206
230
|
data_path=entry,
|
207
231
|
)
|
208
232
|
|
209
|
-
scan_2 =
|
233
|
+
scan_2 = NXtomoScan(file_path, entry)
|
210
234
|
|
211
235
|
# 2.0 create the widget and do the edition
|
212
236
|
widget = NXtomoEditor()
|
File without changes
|
@@ -0,0 +1,80 @@
|
|
1
|
+
from silx.gui import qt
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
|
5
|
+
class CreateRawDataScreenshotsWidget(qt.QWidget):
|
6
|
+
"""
|
7
|
+
Widget to allow the user define the screenshot to make of the raw data
|
8
|
+
"""
|
9
|
+
|
10
|
+
sigConfigChanged = qt.Signal()
|
11
|
+
"""emit when the configuration change"""
|
12
|
+
|
13
|
+
def __init__(self, parent=None):
|
14
|
+
super().__init__(parent)
|
15
|
+
self.setLayout(qt.QFormLayout())
|
16
|
+
# projections
|
17
|
+
self._projectionsCB = qt.QCheckBox("raw projections each", self)
|
18
|
+
self._projectionsSB = qt.QSpinBox(parent)
|
19
|
+
self._projectionsSB.setSuffix("°")
|
20
|
+
self.layout().addRow(self._projectionsCB, self._projectionsSB)
|
21
|
+
# flat field
|
22
|
+
self._flatFieldCB = qt.QCheckBox("first raw flat")
|
23
|
+
self.layout().addRow(self._flatFieldCB)
|
24
|
+
# dark field
|
25
|
+
self._darkFieldCB = qt.QCheckBox("first raw dark")
|
26
|
+
self.layout().addRow(self._darkFieldCB)
|
27
|
+
|
28
|
+
# set up
|
29
|
+
self._projectionsCB.setChecked(True)
|
30
|
+
self._flatFieldCB.setChecked(True)
|
31
|
+
self._darkFieldCB.setChecked(True)
|
32
|
+
|
33
|
+
# connect signal / slot
|
34
|
+
self._projectionsCB.toggled.connect(self._changed)
|
35
|
+
self._projectionsSB.valueChanged.connect(self._changed)
|
36
|
+
self._projectionsSB.setRange(0, 360)
|
37
|
+
self._projectionsSB.setValue(90)
|
38
|
+
self._flatFieldCB.toggled.connect(self._changed)
|
39
|
+
self._darkFieldCB.toggled.connect(self._changed)
|
40
|
+
|
41
|
+
def _changed(self, *args, **kwargs):
|
42
|
+
self.sigConfigChanged.emit()
|
43
|
+
|
44
|
+
def getConfiguration(self) -> dict:
|
45
|
+
return {
|
46
|
+
"raw_projections_required": self._projectionsCB.isChecked(),
|
47
|
+
"raw_projections_each": self._projectionsSB.value(),
|
48
|
+
"raw_darks_required": self._darkFieldCB.isChecked(),
|
49
|
+
"raw_flats_required": self._flatFieldCB.isChecked(),
|
50
|
+
}
|
51
|
+
|
52
|
+
def setRawProjections(self, required: bool, each_proj: Optional[int]):
|
53
|
+
self._projectionsCB.setChecked(required)
|
54
|
+
if each_proj is not None:
|
55
|
+
self._projectionsSB.setValue(int(each_proj))
|
56
|
+
|
57
|
+
def setFlatFieldRequired(self, required: bool):
|
58
|
+
self._flatFieldCB.setChecked(required)
|
59
|
+
|
60
|
+
def setDarkFieldRequired(self, required: bool):
|
61
|
+
self._darkFieldCB.setChecked(required)
|
62
|
+
|
63
|
+
def setConfiguration(self, configuration: dict):
|
64
|
+
assert isinstance(configuration, dict)
|
65
|
+
# handle raw projections
|
66
|
+
raw_projections_required = configuration.get(
|
67
|
+
"raw_projections_required", self._projectionsCB.isChecked()
|
68
|
+
)
|
69
|
+
raw_projections_each = configuration.get("raw_projections_each", None)
|
70
|
+
self.setRawProjections(
|
71
|
+
required=raw_projections_required, each_proj=raw_projections_each
|
72
|
+
)
|
73
|
+
# handle flat field
|
74
|
+
flat_field_required = configuration.get("raw_flats_required", None)
|
75
|
+
if flat_field_required is not None:
|
76
|
+
self.setFlatFieldRequired(flat_field_required)
|
77
|
+
# handle flat field
|
78
|
+
dark_field_required = configuration.get("raw_darks_required", None)
|
79
|
+
if dark_field_required is not None:
|
80
|
+
self.setDarkFieldRequired(dark_field_required)
|
@@ -0,0 +1,214 @@
|
|
1
|
+
import os
|
2
|
+
from silx.gui import qt
|
3
|
+
from silx.utils.enum import Enum as _Enum
|
4
|
+
from tomwer.core.process.icat.gallery import OutputFormat
|
5
|
+
from tomwer.gui.qlefilesystem import QLFileSystem
|
6
|
+
from tomwer.io.utils import get_default_directory
|
7
|
+
from tomwer.core.utils.dictutils import concatenate_dict
|
8
|
+
from tomwer.core.process.icat.gallery import Binning
|
9
|
+
|
10
|
+
from .publish import PublishProcessedDataWidget
|
11
|
+
|
12
|
+
|
13
|
+
class _GalleryOutputDir(qt.QGroupBox):
|
14
|
+
class OutputDirMode(_Enum):
|
15
|
+
DATASET_GALLERY = "dataset gallery"
|
16
|
+
PROPOSAL_GALLERY = "proposal GALLERY"
|
17
|
+
CUSTOM = "custom"
|
18
|
+
|
19
|
+
def __init__(self, parent=None):
|
20
|
+
super().__init__(parent)
|
21
|
+
self.setLayout(qt.QGridLayout())
|
22
|
+
# dataset gallery option
|
23
|
+
self._datasetGalleryQRB = qt.QRadioButton(
|
24
|
+
self.OutputDirMode.DATASET_GALLERY.value, self
|
25
|
+
)
|
26
|
+
self.layout().addWidget(self._datasetGalleryQRB, 0, 0, 1, 4)
|
27
|
+
# proposal gallery option
|
28
|
+
self._proposalGalleryQRB = qt.QRadioButton(
|
29
|
+
self.OutputDirMode.PROPOSAL_GALLERY.value, self
|
30
|
+
)
|
31
|
+
self.layout().addWidget(self._proposalGalleryQRB, 1, 0, 1, 4)
|
32
|
+
|
33
|
+
# other option
|
34
|
+
self._otherQRB = qt.QRadioButton(self.OutputDirMode.CUSTOM.value, self)
|
35
|
+
self._otherQRB.setCheckable(True)
|
36
|
+
self.layout().addWidget(self._otherQRB, 2, 0, 1, 4)
|
37
|
+
|
38
|
+
self._otherQLE = QLFileSystem(
|
39
|
+
"", self, filters=qt.QDir.NoDotAndDotDot | qt.QDir.Dirs
|
40
|
+
)
|
41
|
+
self.layout().addWidget(self._otherQLE, 3, 1, 1, 2)
|
42
|
+
style = qt.QApplication.style()
|
43
|
+
icon_opendir = style.standardIcon(qt.QStyle.SP_DirOpenIcon)
|
44
|
+
self._selectOtherQLE = qt.QPushButton(icon_opendir, "", self)
|
45
|
+
self._selectOtherQLE.setIcon(icon_opendir)
|
46
|
+
self.layout().addWidget(self._selectOtherQLE, 3, 3, 1, 1)
|
47
|
+
|
48
|
+
# button group
|
49
|
+
self._buttonGroup = qt.QButtonGroup()
|
50
|
+
self._buttonGroup.setExclusive(True)
|
51
|
+
self._buttonGroup.addButton(self._datasetGalleryQRB)
|
52
|
+
self._buttonGroup.addButton(self._proposalGalleryQRB)
|
53
|
+
self._buttonGroup.addButton(self._otherQRB)
|
54
|
+
|
55
|
+
# vertical spacer
|
56
|
+
self._vSpacer = qt.QWidget(self)
|
57
|
+
self._vSpacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
|
58
|
+
self.layout().addWidget(self._vSpacer, 99, 0, 1, 1)
|
59
|
+
|
60
|
+
# set up GUI
|
61
|
+
self._datasetGalleryQRB.setChecked(True)
|
62
|
+
self._modeChanged()
|
63
|
+
|
64
|
+
# connect signal / slot
|
65
|
+
self._buttonGroup.buttonClicked.connect(self._modeChanged)
|
66
|
+
self._selectOtherQLE.released.connect(self._selectOutput)
|
67
|
+
|
68
|
+
def _selectOutput(self): # pragma: no cover
|
69
|
+
defaultDirectory = self._selectOtherQLE.text()
|
70
|
+
if not os.path.isdir(defaultDirectory):
|
71
|
+
defaultDirectory = get_default_directory()
|
72
|
+
|
73
|
+
dialog = qt.QFileDialog(self, directory=defaultDirectory)
|
74
|
+
dialog.setFileMode(qt.QFileDialog.DirectoryOnly)
|
75
|
+
|
76
|
+
if not dialog.exec_():
|
77
|
+
dialog.close()
|
78
|
+
return
|
79
|
+
|
80
|
+
self._selectOtherQLE.setText(dialog.selectedFiles()[0])
|
81
|
+
|
82
|
+
def getOutputFolderMode(self):
|
83
|
+
if self._datasetGalleryQRB.isChecked():
|
84
|
+
return _GalleryOutputDir.OutputDirMode.DATASET_GALLERY
|
85
|
+
elif self._proposalGalleryQRB.isChecked():
|
86
|
+
return _GalleryOutputDir.OutputDirMode.PROPOSAL_GALLERY
|
87
|
+
elif self._otherQRB.isChecked():
|
88
|
+
return _GalleryOutputDir.OutputDirMode.CUSTOM
|
89
|
+
else:
|
90
|
+
raise NotImplementedError
|
91
|
+
|
92
|
+
def setOutputFolderMode(self, mode):
|
93
|
+
mode = _GalleryOutputDir.OutputDirMode.from_value(mode)
|
94
|
+
if mode is _GalleryOutputDir.OutputDirMode.PROPOSAL_GALLERY:
|
95
|
+
self._proposalGalleryQRB.setChecked(True)
|
96
|
+
elif mode is _GalleryOutputDir.OutputDirMode.DATASET_GALLERY:
|
97
|
+
self._datasetGalleryQRB.setChecked(True)
|
98
|
+
elif mode is _GalleryOutputDir.OutputDirMode.CUSTOM:
|
99
|
+
self._otherQRB.setChecked(True)
|
100
|
+
else:
|
101
|
+
raise NotImplementedError
|
102
|
+
self._modeChanged()
|
103
|
+
|
104
|
+
def getOtherOutputDir(self):
|
105
|
+
return self._otherQLE.text()
|
106
|
+
|
107
|
+
def setOtherOutputDir(self, path: str):
|
108
|
+
self._otherQLE.setText(path)
|
109
|
+
|
110
|
+
def _modeChanged(self, *args, **kwargs):
|
111
|
+
custom_active = self._otherQRB.isChecked()
|
112
|
+
self._otherQLE.setEnabled(custom_active)
|
113
|
+
self._selectOtherQLE.setEnabled(custom_active)
|
114
|
+
|
115
|
+
|
116
|
+
class GalleryWidget(qt.QWidget):
|
117
|
+
"""Widget to let the user define the output location of the screenshots"""
|
118
|
+
|
119
|
+
sigConfigChanged = qt.Signal()
|
120
|
+
"""emit when the configuration has changed"""
|
121
|
+
|
122
|
+
def __init__(self, parent=None):
|
123
|
+
super().__init__(parent)
|
124
|
+
self.setLayout(qt.QFormLayout())
|
125
|
+
|
126
|
+
# screenshot precision
|
127
|
+
self._precisonQCB = qt.QComboBox(self)
|
128
|
+
self._precisonQCB.addItem("uint8")
|
129
|
+
self.layout().addRow("precision", self._precisonQCB)
|
130
|
+
# binning
|
131
|
+
self._binningQCB = qt.QComboBox(self)
|
132
|
+
self._binningQCB.addItems(Binning.values())
|
133
|
+
self.layout().addRow("binning", self._binningQCB)
|
134
|
+
self._binningQCB.setCurrentText(Binning.SIXTEEN_BY_SIXTEEN.value)
|
135
|
+
self._binningQCB.setToolTip(
|
136
|
+
"To speed up display of the gallery at the data portal side it is highly recommended to bin screenshots"
|
137
|
+
) # recommanded size: 5ko for the entire gallery
|
138
|
+
# output format
|
139
|
+
self._outputFormat = qt.QComboBox(self)
|
140
|
+
self._outputFormat.addItems(OutputFormat.values())
|
141
|
+
self.layout().addRow("outoutput_location_modeput format", self._outputFormat)
|
142
|
+
# gallery output dir
|
143
|
+
self._outputDirWidget = _GalleryOutputDir(self)
|
144
|
+
self._outputLocationLabel = qt.QLabel("output location", self)
|
145
|
+
self.layout().addRow(self._outputLocationLabel, self._outputDirWidget)
|
146
|
+
self._outputDirWidget.hide()
|
147
|
+
self._outputLocationLabel.hide()
|
148
|
+
# overwrite
|
149
|
+
self._overwriteCB = qt.QCheckBox("overwrite", self)
|
150
|
+
self._overwriteCB.setChecked(True)
|
151
|
+
self.layout().addRow(self._overwriteCB)
|
152
|
+
# publishing setting
|
153
|
+
self._publishConfig = PublishProcessedDataWidget(self)
|
154
|
+
self._publisherGB = qt.QGroupBox("icat info")
|
155
|
+
self._publisherGB.setLayout(qt.QVBoxLayout())
|
156
|
+
self._publisherGB.layout().addWidget(self._publishConfig)
|
157
|
+
self.layout().addRow(self._publisherGB)
|
158
|
+
# connect signal / slot
|
159
|
+
self._outputFormat.currentIndexChanged.connect(self._configChanged)
|
160
|
+
self._overwriteCB.toggled.connect(self._configChanged)
|
161
|
+
self._publishConfig.sigConfigChanged.connect(self.sigConfigChanged)
|
162
|
+
self._binningQCB.currentIndexChanged.connect(self._configChanged)
|
163
|
+
|
164
|
+
def getOutputFormat(self) -> OutputFormat:
|
165
|
+
return OutputFormat.from_value(self._outputFormat.currentText())
|
166
|
+
|
167
|
+
def setOutputFormat(self, format: OutputFormat):
|
168
|
+
format = OutputFormat.from_value(format)
|
169
|
+
self._outputFormat.setCurrentText(format.value)
|
170
|
+
|
171
|
+
def getBinning(self) -> Binning:
|
172
|
+
return Binning.from_value(self._binningQCB.currentText())
|
173
|
+
|
174
|
+
def setBinning(self, binning: Binning):
|
175
|
+
binning = Binning.from_value(binning)
|
176
|
+
self._binningQCB.setCurrentText(binning.value)
|
177
|
+
|
178
|
+
def getConfiguration(self):
|
179
|
+
return concatenate_dict(
|
180
|
+
self._publishConfig.getConfiguration(),
|
181
|
+
{
|
182
|
+
"output_format": self.getOutputFormat().value,
|
183
|
+
"output_location_mode": self._outputDirWidget.getOutputFolderMode().value,
|
184
|
+
"custom_output": self._outputDirWidget.getOtherOutputDir(),
|
185
|
+
"overwrite": self._overwriteCB.isChecked(),
|
186
|
+
"binning": self.getBinning().value,
|
187
|
+
},
|
188
|
+
)
|
189
|
+
|
190
|
+
def setConfiguration(self, config: dict):
|
191
|
+
self._publishConfig.setConfiguration(config)
|
192
|
+
output_format = config.get("output_format", None)
|
193
|
+
if output_format is not None:
|
194
|
+
self.setOutputFormat(output_format)
|
195
|
+
|
196
|
+
output_location_mode = config.get("output_location_mode", None)
|
197
|
+
if output_location_mode is not None:
|
198
|
+
self._outputDirWidget.setOutputFolderMode(output_location_mode)
|
199
|
+
|
200
|
+
custom_output = config.get("custom_output", None)
|
201
|
+
if custom_output is not None:
|
202
|
+
self._outputDirWidget.setOtherOutputDir(custom_output)
|
203
|
+
|
204
|
+
overwrite = config.get("overwrite", None)
|
205
|
+
if overwrite is not None:
|
206
|
+
overwrite = overwrite in (True, "True", 1)
|
207
|
+
self._overwriteCB.setChecked(overwrite)
|
208
|
+
|
209
|
+
binning = config.get("binning", None)
|
210
|
+
if binning is not None:
|
211
|
+
self.setBinning(binning=binning)
|
212
|
+
|
213
|
+
def _configChanged(self, *args, **kwargs):
|
214
|
+
self.sigConfigChanged.emit()
|
@@ -0,0 +1,187 @@
|
|
1
|
+
import platform
|
2
|
+
from silx.gui import qt
|
3
|
+
from tomwer.core.scan.scanbase import TomwerScanBase
|
4
|
+
from tomwer.gui.utils.qt_utils import block_signals
|
5
|
+
from tomwer.gui.utils.buttons import PadlockButton
|
6
|
+
|
7
|
+
|
8
|
+
class PublishProcessedDataWidget(qt.QWidget):
|
9
|
+
sigConfigChanged = qt.Signal()
|
10
|
+
"""emit when the configuration changed"""
|
11
|
+
|
12
|
+
KNOW_BEAMLINES = sorted(
|
13
|
+
("bm05", "bm18", "id11", "id15a", "id16a", "id16b", "id17", "id19")
|
14
|
+
)
|
15
|
+
|
16
|
+
_TOOLTIP_PAD_LOCKS = "when receive a new scan the value will be updated if valid informations are found. If the field is lock then no update will be done automatically."
|
17
|
+
|
18
|
+
def __init__(self, parent=None) -> None:
|
19
|
+
super().__init__(parent)
|
20
|
+
self.setLayout(qt.QGridLayout())
|
21
|
+
|
22
|
+
# beamline
|
23
|
+
self._beamlineCB = qt.QComboBox(self)
|
24
|
+
self._beamlineCB.setEditable(True)
|
25
|
+
self._beamlineCB.addItems(self.KNOW_BEAMLINES)
|
26
|
+
self._beamlineCB.lineEdit().setPlaceholderText("beamline name")
|
27
|
+
self.layout().addWidget(
|
28
|
+
qt.QLabel("beamline", self),
|
29
|
+
0,
|
30
|
+
0,
|
31
|
+
1,
|
32
|
+
1,
|
33
|
+
)
|
34
|
+
self.layout().addWidget(
|
35
|
+
self._beamlineCB,
|
36
|
+
0,
|
37
|
+
1,
|
38
|
+
1,
|
39
|
+
1,
|
40
|
+
)
|
41
|
+
self._beamlinePLB = PadlockButton(self)
|
42
|
+
self._beamlinePLB.setToolTip(self._TOOLTIP_PAD_LOCKS)
|
43
|
+
self.layout().addWidget(
|
44
|
+
self._beamlinePLB,
|
45
|
+
0,
|
46
|
+
2,
|
47
|
+
1,
|
48
|
+
1,
|
49
|
+
)
|
50
|
+
|
51
|
+
# proposal
|
52
|
+
self._proposalQLE = qt.QLineEdit("", self)
|
53
|
+
self._proposalQLE.setPlaceholderText("proposal name")
|
54
|
+
self.layout().addWidget(
|
55
|
+
qt.QLabel("proposal", self),
|
56
|
+
1,
|
57
|
+
0,
|
58
|
+
1,
|
59
|
+
1,
|
60
|
+
)
|
61
|
+
self.layout().addWidget(
|
62
|
+
self._proposalQLE,
|
63
|
+
1,
|
64
|
+
1,
|
65
|
+
1,
|
66
|
+
1,
|
67
|
+
)
|
68
|
+
self._proposalPLB = PadlockButton(self)
|
69
|
+
self._proposalPLB.setToolTip(self._TOOLTIP_PAD_LOCKS)
|
70
|
+
self.layout().addWidget(
|
71
|
+
self._proposalPLB,
|
72
|
+
1,
|
73
|
+
2,
|
74
|
+
1,
|
75
|
+
1,
|
76
|
+
)
|
77
|
+
|
78
|
+
# dataset
|
79
|
+
self._datasetQLE = qt.QLineEdit("", self)
|
80
|
+
self._datasetQLE.setPlaceholderText("dataset name")
|
81
|
+
self.layout().addWidget(
|
82
|
+
qt.QLabel("dataset", self),
|
83
|
+
2,
|
84
|
+
0,
|
85
|
+
1,
|
86
|
+
1,
|
87
|
+
)
|
88
|
+
self.layout().addWidget(
|
89
|
+
self._datasetQLE,
|
90
|
+
2,
|
91
|
+
1,
|
92
|
+
1,
|
93
|
+
1,
|
94
|
+
)
|
95
|
+
self._datasetPLB = PadlockButton(self)
|
96
|
+
self._datasetPLB.setToolTip(self._TOOLTIP_PAD_LOCKS)
|
97
|
+
self.layout().addWidget(
|
98
|
+
self._datasetPLB,
|
99
|
+
2,
|
100
|
+
2,
|
101
|
+
1,
|
102
|
+
1,
|
103
|
+
)
|
104
|
+
|
105
|
+
# set up
|
106
|
+
default_beamline = self.getDefaultBeamline()
|
107
|
+
if default_beamline is not None:
|
108
|
+
self._beamlineCB.setCurrentText(default_beamline)
|
109
|
+
|
110
|
+
# connect signal / slot
|
111
|
+
self._beamlinePLB.toggled.connect(self._configChanged)
|
112
|
+
self._proposalPLB.toggled.connect(self._configChanged)
|
113
|
+
self._datasetPLB.toggled.connect(self._configChanged)
|
114
|
+
self._beamlineCB.currentTextChanged.connect(self._configChanged)
|
115
|
+
self._proposalQLE.textEdited.connect(self._configChanged)
|
116
|
+
self._datasetQLE.textEdited.connect(self._configChanged)
|
117
|
+
|
118
|
+
@staticmethod
|
119
|
+
def getDefaultBeamline():
|
120
|
+
hostname = platform.node()
|
121
|
+
for beamline in PublishProcessedDataWidget.KNOW_BEAMLINES:
|
122
|
+
if beamline in hostname:
|
123
|
+
return beamline
|
124
|
+
|
125
|
+
return None
|
126
|
+
|
127
|
+
def set_auto_update(self, update: bool):
|
128
|
+
self._beamlinePLB.setChecked(not update)
|
129
|
+
self._proposalPLB.setChecked(not update)
|
130
|
+
self._datasetPLB.setChecked(not update)
|
131
|
+
|
132
|
+
def _configChanged(self, *args, **kwargs):
|
133
|
+
self.sigConfigChanged.emit()
|
134
|
+
|
135
|
+
def getConfiguration(self) -> dict:
|
136
|
+
return {
|
137
|
+
"beamline_auto_update": not self._beamlinePLB.isChecked(),
|
138
|
+
"dataset_auto_update": not self._datasetPLB.isChecked(),
|
139
|
+
"proposal_auto_update": not self._proposalPLB.isChecked(),
|
140
|
+
"beamline": self._beamlineCB.currentText(),
|
141
|
+
"dataset": self._datasetQLE.text(),
|
142
|
+
"proposal": self._proposalQLE.text(),
|
143
|
+
}
|
144
|
+
|
145
|
+
def setConfiguration(self, configuration: dict):
|
146
|
+
with block_signals(self):
|
147
|
+
# handle beamline
|
148
|
+
beamline = configuration.get("beamline", None)
|
149
|
+
if beamline is not None:
|
150
|
+
self._beamlineCB.setCurrentText(beamline)
|
151
|
+
beamline_auto_update = configuration.get("beamline_auto_update", None)
|
152
|
+
if beamline_auto_update is not None:
|
153
|
+
self._beamlinePLB.setChecked(not beamline_auto_update)
|
154
|
+
|
155
|
+
# handle dataset
|
156
|
+
dataset = configuration.get("dataset", None)
|
157
|
+
if dataset is not None:
|
158
|
+
self._datasetQLE.setText(dataset)
|
159
|
+
dataset_auto_update = configuration.get("dataset_auto_update", None)
|
160
|
+
if dataset_auto_update is not None:
|
161
|
+
self._datasetPLB.setChecked(not dataset_auto_update)
|
162
|
+
|
163
|
+
# handle proposal
|
164
|
+
proposal = configuration.get("proposal", None)
|
165
|
+
if proposal is not None:
|
166
|
+
self._proposalQLE.setText(proposal)
|
167
|
+
proposal_auto_update = configuration.get("proposal_auto_update", None)
|
168
|
+
if proposal_auto_update is not None:
|
169
|
+
self._proposalPLB.setChecked(not proposal_auto_update)
|
170
|
+
|
171
|
+
self._configChanged()
|
172
|
+
|
173
|
+
def setScan(self, scan: TomwerScanBase):
|
174
|
+
if not isinstance(scan, TomwerScanBase):
|
175
|
+
raise TypeError(
|
176
|
+
f"scan is expected to be an instance of {TomwerScanBase}, {type(scan)} provided instead"
|
177
|
+
)
|
178
|
+
|
179
|
+
new_config = {}
|
180
|
+
if not self._proposalPLB.isChecked():
|
181
|
+
new_config["proposal"] = scan.get_proposal_name()
|
182
|
+
if not self._beamlinePLB.isChecked():
|
183
|
+
new_config["beamline"] = scan.instrument_name
|
184
|
+
if not self._datasetPLB.isChecked():
|
185
|
+
new_config["dataset"] = scan.sample_name
|
186
|
+
|
187
|
+
self.setConfiguration(new_config)
|