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
@@ -1,896 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# /*##########################################################################
|
3
|
-
#
|
4
|
-
# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
|
5
|
-
#
|
6
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
-
# of this software and associated documentation files (the "Software"), to deal
|
8
|
-
# in the Software without restriction, including without limitation the rights
|
9
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
-
# copies of the Software, and to permit persons to whom the Software is
|
11
|
-
# furnished to do so, subject to the following conditions:
|
12
|
-
#
|
13
|
-
# The above copyright notice and this permission notice shall be included in
|
14
|
-
# all copies or substantial portions of the Software.
|
15
|
-
#
|
16
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
-
# THE SOFTWARE.
|
23
|
-
#
|
24
|
-
# ###########################################################################*/
|
25
|
-
|
26
|
-
__authors__ = ["H. Payno"]
|
27
|
-
__license__ = "MIT"
|
28
|
-
__date__ = "01/06/2018"
|
29
|
-
|
30
|
-
|
31
|
-
import logging
|
32
|
-
import os
|
33
|
-
|
34
|
-
from silx.gui import qt
|
35
|
-
|
36
|
-
from tomwer.core.process.reconstruction.lamino.tofu import FFCWhen, getDark, getFlats
|
37
|
-
from tomwer.core.utils import (
|
38
|
-
getClosestEnergy,
|
39
|
-
getDARK_N,
|
40
|
-
getDim1Dim2,
|
41
|
-
getParametersFromParOrInfo,
|
42
|
-
getPixelSize,
|
43
|
-
getTomo_N,
|
44
|
-
)
|
45
|
-
from tomwer.core.utils.char import PSI_CHAR, THETA_CHAR
|
46
|
-
from tomwer.gui import icons
|
47
|
-
from tomwer.gui.utils.illustrations import _IllustrationDialog, _IllustrationWidget
|
48
|
-
from tomwer.gui.utils.unitsystem import MetricEntry
|
49
|
-
|
50
|
-
from .misc import PadlockButton, _AngleWidget
|
51
|
-
from .TofuOptionLoader import _getterSetter, _TofuOptionLoader
|
52
|
-
|
53
|
-
_logger = logging.getLogger(__name__)
|
54
|
-
|
55
|
-
|
56
|
-
class InputProjectionsScrollArea(qt.QScrollArea):
|
57
|
-
def __init__(self, parent):
|
58
|
-
qt.QScrollArea.__init__(self, parent)
|
59
|
-
self.widget = InputProjectionsWidget(parent=self)
|
60
|
-
self.setWidget(self.widget)
|
61
|
-
self.setWidgetResizable(True)
|
62
|
-
|
63
|
-
# expose API
|
64
|
-
self.loadFromScan = self.widget.loadFromScan
|
65
|
-
self.setNumber = self.widget.setNumber
|
66
|
-
self.getNumber = self.widget.getNumber
|
67
|
-
self.getPixelSize = self.widget.getPixelSize
|
68
|
-
self.setPixelSize = self.widget.setPixelSize
|
69
|
-
self.pixelSizeIsLocked = self.widget.pixelSizeIsLocked
|
70
|
-
self.getParameters = self.widget.getParameters
|
71
|
-
self.loadFromScan = self.widget.loadFromScan
|
72
|
-
self.setParameters = self.widget.setParameters
|
73
|
-
self.rotationAngle = self.widget.rotationAngle
|
74
|
-
self.centeringWidget = self.widget.centeringWidget
|
75
|
-
self.getWhenApplyFFC = self.widget.getWhenApplyFFC
|
76
|
-
self.setWhenApplyFFC = self.widget.setWhenApplyFFC
|
77
|
-
self.isHalfAcquisition = self.widget.isHalfAcquisition
|
78
|
-
self.setHalfAcquisition = self.widget.setHalfAcquisition
|
79
|
-
self.setBlend = self.widget.setBlend
|
80
|
-
self.setAdjustMean = self.widget.setAdjustMean
|
81
|
-
|
82
|
-
|
83
|
-
class InputProjectionsWidget(_TofuOptionLoader, qt.QWidget):
|
84
|
-
"""TabWidget containing all the information relative to the
|
85
|
-
flat field correction"""
|
86
|
-
|
87
|
-
def __init__(self, parent):
|
88
|
-
qt.QWidget.__init__(self, parent)
|
89
|
-
self.setLayout(qt.QGridLayout())
|
90
|
-
|
91
|
-
self.rotationAngle = RotationAngleGroupBox(parent=self)
|
92
|
-
self.layout().addWidget(self.rotationAngle, 0, 0)
|
93
|
-
|
94
|
-
self.centeringWidget = CenteringTofuGroupBox(parent=self)
|
95
|
-
self.layout().addWidget(self.centeringWidget, 1, 0)
|
96
|
-
|
97
|
-
self._numberOfFiles = NbFilesWidget(parent=self)
|
98
|
-
self._numberOfFiles.layout().setContentsMargins(6, 2, 2, 2)
|
99
|
-
self.layout().addWidget(self._numberOfFiles, 2, 0)
|
100
|
-
|
101
|
-
# pixel size
|
102
|
-
self._pixelWidget = qt.QWidget(parent=self)
|
103
|
-
self._pixelWidget.setLayout(qt.QHBoxLayout())
|
104
|
-
self._pixelWidget.layout().setContentsMargins(6, 2, 2, 2)
|
105
|
-
|
106
|
-
self._pixelSize = MetricEntry(name="pixel size", parent=self, default_unit="m")
|
107
|
-
self._pixelWidget.layout().addWidget(self._pixelSize._label)
|
108
|
-
self._pixelWidget.layout().addWidget(self._pixelSize._qlePixelSize)
|
109
|
-
self._pixelWidget.layout().addWidget(self._pixelSize._qcbUnit)
|
110
|
-
self._pixelSizeLockButton = PadlockButton(parent=self)
|
111
|
-
self._pixelWidget.layout().addWidget(self._pixelSizeLockButton)
|
112
|
-
self.layout().addWidget(self._pixelWidget, 3, 0)
|
113
|
-
|
114
|
-
# half & options
|
115
|
-
self._halfAcqWidget = qt.QWidget(parent=self)
|
116
|
-
self._halfAcqWidget.setLayout(qt.QHBoxLayout())
|
117
|
-
self._halfAcqWidget.layout().setContentsMargins(6, 2, 2, 2)
|
118
|
-
self._halfAcqCB = qt.QCheckBox("half acquisition", parent=self)
|
119
|
-
self._halfAcqWidget.layout().addWidget(self._halfAcqCB)
|
120
|
-
self._blendCB = qt.QCheckBox("blend", parent=self)
|
121
|
-
self._blendCB.setVisible(False)
|
122
|
-
self._halfAcqWidget.layout().addWidget(self._blendCB)
|
123
|
-
self._adjustMeanCB = qt.QCheckBox("adjust mean", parent=self)
|
124
|
-
self._adjustMeanCB.setVisible(False)
|
125
|
-
self._halfAcqWidget.layout().addWidget(self._adjustMeanCB)
|
126
|
-
self.layout().addWidget(self._halfAcqWidget, 4, 0)
|
127
|
-
|
128
|
-
# flat field correction
|
129
|
-
self._ffcWidget = _FFCConfigWidget(parent=self)
|
130
|
-
self.layout().addWidget(self._ffcWidget, 5, 0, 2, 2)
|
131
|
-
|
132
|
-
self._phaseRetrieval = PhaseRetrievalWidget(parent=self)
|
133
|
-
self._phaseRetrieval.setCheckable(True)
|
134
|
-
self._phaseRetrieval.setChecked(False)
|
135
|
-
self.layout().addWidget(self._phaseRetrieval, 7, 0)
|
136
|
-
|
137
|
-
spacer = qt.QWidget(self)
|
138
|
-
spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
|
139
|
-
self.layout().addWidget(spacer)
|
140
|
-
|
141
|
-
self._ffcWidget._absortivityActivated.connect(self._phaseRetrieval.setUnchecked)
|
142
|
-
self._phaseRetrieval.activated.connect(self._ffcWidget.uncheckedAbsorptivity)
|
143
|
-
|
144
|
-
# expose API
|
145
|
-
self.setNumber = self._numberOfFiles.setNumberOfFiles
|
146
|
-
self.getNumber = self._numberOfFiles.getNumberOfFiles
|
147
|
-
self.getPixelSize = self._pixelSize.getValue
|
148
|
-
self.setPixelSize = self._pixelSize.setValue
|
149
|
-
self.pixelSizeIsLocked = self._pixelSizeLockButton.isLocked
|
150
|
-
self.getWhenApplyFFC = self._ffcWidget.getWhenApplyFFC
|
151
|
-
self.setWhenApplyFFC = self._ffcWidget.setWhenApplyFFC
|
152
|
-
self.isHalfAcquisition = self._halfAcqCB.isChecked
|
153
|
-
self.setHalfAcquisition = self._halfAcqCB.setChecked
|
154
|
-
self.isBlend = self._blendCB.isChecked
|
155
|
-
self.setBlend = self._blendCB.setChecked
|
156
|
-
self.isAdjustMean = self._adjustMeanCB.isChecked
|
157
|
-
self.setAdjustMean = self._adjustMeanCB.setChecked
|
158
|
-
|
159
|
-
options = {
|
160
|
-
"ffc-when": _getterSetter(
|
161
|
-
getter=self.getWhenApplyFFC, setter=self.setWhenApplyFFC
|
162
|
-
),
|
163
|
-
"number": _getterSetter(getter=self.getNumber, setter=self.setNumber),
|
164
|
-
"reduction-mode": _getterSetter(
|
165
|
-
getter=self._ffcWidget.getMethod, setter=self._ffcWidget.setMethod
|
166
|
-
),
|
167
|
-
"darks": _getterSetter(
|
168
|
-
getter=self._ffcWidget.getDarks, setter=self._ffcWidget.setDarks
|
169
|
-
),
|
170
|
-
"flats": _getterSetter(
|
171
|
-
getter=self._ffcWidget.getFlats, setter=self._ffcWidget.setFlats
|
172
|
-
),
|
173
|
-
"flats2": _getterSetter(
|
174
|
-
getter=self._ffcWidget.getSecondFlats,
|
175
|
-
setter=self._ffcWidget.setSecondFlats,
|
176
|
-
),
|
177
|
-
"absorptivity": _getterSetter(
|
178
|
-
getter=self._ffcWidget.requireAbsorptivity,
|
179
|
-
setter=self._ffcWidget.setAbsortivity,
|
180
|
-
),
|
181
|
-
"fix-nan-and-inf": _getterSetter(
|
182
|
-
getter=self._ffcWidget.removeNanAndInf,
|
183
|
-
setter=self._ffcWidget.setNanAndInf,
|
184
|
-
),
|
185
|
-
"dark-scale": _getterSetter(
|
186
|
-
getter=self._ffcWidget.getDarkScale, setter=self._ffcWidget.setDarkScale
|
187
|
-
),
|
188
|
-
"axis-angle-x": _getterSetter(
|
189
|
-
getter=self.rotationAngle._laminoAngle.getAngle,
|
190
|
-
setter=self.rotationAngle._laminoAngle.setAngle,
|
191
|
-
),
|
192
|
-
"axis-angle-y": _getterSetter(
|
193
|
-
getter=self.rotationAngle._axisAngleY.getAngle,
|
194
|
-
setter=self.rotationAngle._axisAngleY.setAngle,
|
195
|
-
),
|
196
|
-
"axis-angle-z": _getterSetter(
|
197
|
-
getter=self.rotationAngle._axisAngleZ.getAngle,
|
198
|
-
setter=self.rotationAngle._axisAngleZ.setAngle,
|
199
|
-
),
|
200
|
-
"center-position-x": _getterSetter(
|
201
|
-
getter=self.centeringWidget.getXCenter,
|
202
|
-
setter=self.centeringWidget.setXCenter,
|
203
|
-
),
|
204
|
-
"center-position-z": _getterSetter(
|
205
|
-
getter=self.centeringWidget.getZCenter,
|
206
|
-
setter=self.centeringWidget.setZCenter,
|
207
|
-
),
|
208
|
-
"overall-angle": _getterSetter(
|
209
|
-
getter=self.rotationAngle._overallAngle.getAngle,
|
210
|
-
setter=self.rotationAngle._setOverallAngleI,
|
211
|
-
),
|
212
|
-
"pixel-size": _getterSetter(
|
213
|
-
getter=self.getPixelSize, setter=self.setPixelSize
|
214
|
-
),
|
215
|
-
"half-acquisition": _getterSetter(
|
216
|
-
getter=self.isHalfAcquisition, setter=self._halfAcqCB.setChecked
|
217
|
-
),
|
218
|
-
"blend": _getterSetter(getter=self.isBlend, setter=self.setBlend),
|
219
|
-
"adjust-mean": _getterSetter(
|
220
|
-
getter=self.isAdjustMean, setter=self.setAdjustMean
|
221
|
-
),
|
222
|
-
}
|
223
|
-
_TofuOptionLoader.__init__(self, options=options, childs=[self._phaseRetrieval])
|
224
|
-
|
225
|
-
# connect
|
226
|
-
self._halfAcqCB.toggled.connect(self._updateFFCOptions)
|
227
|
-
|
228
|
-
def _updateFFCOptions(self):
|
229
|
-
# if we want the half acquisition, for now we force the ffc to be done
|
230
|
-
# in preprocessing
|
231
|
-
self._ffcWidget.forcePreprocessing(self._halfAcqCB.isChecked())
|
232
|
-
self._blendCB.setVisible(self._halfAcqCB.isChecked())
|
233
|
-
self._adjustMeanCB.setVisible(self._halfAcqCB.isChecked())
|
234
|
-
|
235
|
-
def loadFromScan(self, scanID):
|
236
|
-
if scanID is None:
|
237
|
-
return
|
238
|
-
try:
|
239
|
-
nFile = getTomo_N(scanID)
|
240
|
-
self.setNumber(nFile)
|
241
|
-
except Exception as error:
|
242
|
-
_logger.error(error)
|
243
|
-
|
244
|
-
self.rotationAngle.loadFromScan(scanID=scanID)
|
245
|
-
self.centeringWidget.loadFromScan(scanID=scanID)
|
246
|
-
self._ffcWidget.loadFromScan(scanID=scanID)
|
247
|
-
self._phaseRetrieval.loadFromScan(scanID=scanID)
|
248
|
-
|
249
|
-
pixelSize = getPixelSize(scanID)
|
250
|
-
if pixelSize is not None and self.pixelSizeIsLocked() is False:
|
251
|
-
self.setPixelSize(float(pixelSize))
|
252
|
-
|
253
|
-
|
254
|
-
class _FFCConfigWidget(qt.QGroupBox):
|
255
|
-
"""Widget dedicated to the parameters used for the flat field correction"""
|
256
|
-
|
257
|
-
_absortivityActivated = qt.Signal()
|
258
|
-
"""Signal emitted when the absorptivity is activated"""
|
259
|
-
|
260
|
-
def __init__(self, parent):
|
261
|
-
super(_FFCConfigWidget, self).__init__("flat field correction", parent)
|
262
|
-
self.setLayout(qt.QGridLayout())
|
263
|
-
|
264
|
-
self._whenGrp = _FFCWhenWidget(parent=self)
|
265
|
-
self.layout().addWidget(qt.QLabel("when"), 0, 0)
|
266
|
-
self.layout().addWidget(self._whenGrp, 0, 1)
|
267
|
-
|
268
|
-
self.layout().addWidget(qt.QLabel("method"), 1, 0)
|
269
|
-
self._method = qt.QComboBox(parent=self)
|
270
|
-
self._method.addItem("median")
|
271
|
-
self._method.addItem("Average")
|
272
|
-
self.layout().addWidget(self._method, 1, 1)
|
273
|
-
|
274
|
-
self.__absortivityLabel = qt.QLabel("absorptivity (*)")
|
275
|
-
self.__absortivityLabel.setToolTip(
|
276
|
-
"Activating absortivity will " "deactivate phase retrieval"
|
277
|
-
)
|
278
|
-
self.layout().addWidget(self.__absortivityLabel, 2, 0)
|
279
|
-
|
280
|
-
self._absortivity = qt.QCheckBox(parent=self)
|
281
|
-
self.layout().addWidget(self._absortivity, 2, 1)
|
282
|
-
self._absortivity.setChecked(True)
|
283
|
-
|
284
|
-
self.layout().addWidget(qt.QLabel("remove Nan and Inf"), 3, 0)
|
285
|
-
self._removeNanInf = qt.QCheckBox(parent=self)
|
286
|
-
self.layout().addWidget(self._removeNanInf, 3, 1)
|
287
|
-
self._removeNanInf.setChecked(True)
|
288
|
-
|
289
|
-
self.layout().addWidget(qt.QLabel("dark scale"), 4, 0)
|
290
|
-
self._darkScaleSB = qt.QDoubleSpinBox(parent=self)
|
291
|
-
self._darkScaleSB.setMinimum(0.0)
|
292
|
-
self._darkScaleSB.setValue(1.0)
|
293
|
-
self._darkScaleSB.setSingleStep(0.1)
|
294
|
-
self.layout().addWidget(self._darkScaleSB, 4, 1)
|
295
|
-
|
296
|
-
self.layout().addWidget(qt.QLabel("darks"), 5, 0)
|
297
|
-
self._darksLE = qt.QLineEdit("", parent=self)
|
298
|
-
self.layout().addWidget(self._darksLE, 5, 1)
|
299
|
-
self.layout().addWidget(qt.QLabel("flats"), 6, 0)
|
300
|
-
self._flatsLE = qt.QLineEdit("", parent=self)
|
301
|
-
self.layout().addWidget(self._flatsLE, 6, 1)
|
302
|
-
|
303
|
-
self.layout().addWidget(qt.QLabel("second flats"), 7, 0)
|
304
|
-
self._secondFlatsLE = qt.QLineEdit("", parent=self)
|
305
|
-
self.layout().addWidget(self._secondFlatsLE, 7, 1)
|
306
|
-
|
307
|
-
self._absortivity.toggled.connect(self._absortivityStatusChanged)
|
308
|
-
|
309
|
-
# expose API
|
310
|
-
self.getWhenApplyFFC = self._whenGrp.getWhen
|
311
|
-
self.setWhenApplyFFC = self._whenGrp.setWhen
|
312
|
-
self.forcePreprocessing = self._whenGrp.forcePreprocessing
|
313
|
-
|
314
|
-
def _absortivityStatusChanged(self, checked):
|
315
|
-
if checked is True:
|
316
|
-
self._absortivityActivated.emit()
|
317
|
-
|
318
|
-
def uncheckedAbsorptivity(self):
|
319
|
-
self._absortivity.setChecked(False)
|
320
|
-
|
321
|
-
def getMethod(self):
|
322
|
-
return self._method.currentText()
|
323
|
-
|
324
|
-
def setMethod(self, method):
|
325
|
-
_method = method
|
326
|
-
if _method.lower == "median":
|
327
|
-
_method = "median"
|
328
|
-
if _method.title() == "Average":
|
329
|
-
_method = "Average"
|
330
|
-
index = self._method.findText(_method)
|
331
|
-
if index < 0:
|
332
|
-
_logger.warning("fail to set method %s, unrecognized method: ", _method)
|
333
|
-
else:
|
334
|
-
self._method.setCurrentIndex(index)
|
335
|
-
|
336
|
-
def setAbsortivity(self, value=True):
|
337
|
-
_value = value
|
338
|
-
if _value == "":
|
339
|
-
_value = True
|
340
|
-
self._absortivity.setChecked(_value)
|
341
|
-
|
342
|
-
def setNanAndInf(self, value=True):
|
343
|
-
_value = value
|
344
|
-
if _value == "":
|
345
|
-
_value = True
|
346
|
-
self._removeNanInf.setChecked(_value)
|
347
|
-
|
348
|
-
def requireAbsorptivity(self):
|
349
|
-
return self._absortivity.isChecked()
|
350
|
-
|
351
|
-
def removeNanAndInf(self):
|
352
|
-
return self._removeNanInf.isChecked()
|
353
|
-
|
354
|
-
def getDarks(self):
|
355
|
-
if self._darksLE.text() == "":
|
356
|
-
return None
|
357
|
-
else:
|
358
|
-
return self._darksLE.text()
|
359
|
-
|
360
|
-
def setDarks(self, val):
|
361
|
-
self._darksLE.setText(val)
|
362
|
-
|
363
|
-
def getFlats(self):
|
364
|
-
if self._flatsLE.text() == "":
|
365
|
-
return None
|
366
|
-
else:
|
367
|
-
return self._flatsLE.text()
|
368
|
-
|
369
|
-
def setFlats(self, val):
|
370
|
-
self._flatsLE.setText(val)
|
371
|
-
|
372
|
-
def getSecondFlats(self):
|
373
|
-
if self._secondFlatsLE.text() == "":
|
374
|
-
return None
|
375
|
-
else:
|
376
|
-
return self._secondFlatsLE.text()
|
377
|
-
|
378
|
-
def setSecondFlats(self, val):
|
379
|
-
self._secondFlatsLE.setText(val)
|
380
|
-
|
381
|
-
def hasDarks(self):
|
382
|
-
return self._darksLE.text() != ""
|
383
|
-
|
384
|
-
def getDarkScale(self):
|
385
|
-
if self.hasDarks() is False:
|
386
|
-
return None
|
387
|
-
else:
|
388
|
-
return float(self._darkScaleSB.value())
|
389
|
-
|
390
|
-
def setDarkScale(self, value):
|
391
|
-
if value is not None:
|
392
|
-
self._darkScaleSB.setValue(float(value))
|
393
|
-
|
394
|
-
def resetDarkScale(self):
|
395
|
-
self._darkScaleSB.setValue(1.0)
|
396
|
-
|
397
|
-
def loadFromScan(self, scanID):
|
398
|
-
try:
|
399
|
-
flats, secondFlat = getFlats(scan=scanID)
|
400
|
-
self.setFlats(flats or "")
|
401
|
-
self.setSecondFlats(secondFlat or "")
|
402
|
-
darkN = getDARK_N(scanID)
|
403
|
-
if darkN is not None:
|
404
|
-
self._darkScaleSB.setValue(1.0 / int(darkN))
|
405
|
-
darkFile = getDark(scan=scanID)
|
406
|
-
if darkFile is not None:
|
407
|
-
self.setDarks(darkFile)
|
408
|
-
# in this case dark is already normalized, set dark scale to 1.0
|
409
|
-
if os.path.basename(darkFile) in ("dark.edf", "darkHST.edf"):
|
410
|
-
self.resetDarkScale()
|
411
|
-
except Exception as error:
|
412
|
-
_logger.error(error)
|
413
|
-
|
414
|
-
|
415
|
-
class _FFCWhenWidget(qt.QWidget):
|
416
|
-
def __init__(self, parent):
|
417
|
-
qt.QWidget.__init__(self, parent)
|
418
|
-
self.setLayout(qt.QHBoxLayout())
|
419
|
-
self.layout().setContentsMargins(0, 0, 0, 0)
|
420
|
-
self._group = qt.QButtonGroup(parent=self)
|
421
|
-
|
422
|
-
name = FFCWhen.on_the_fly.name.replace("_", " ")
|
423
|
-
self._onTheFlyQRB = qt.QRadioButton(name, self)
|
424
|
-
self._onTheFlyQRB.setToolTip(
|
425
|
-
"process flat field correction during "
|
426
|
-
"reconstruction. Avoid multiple io read."
|
427
|
-
)
|
428
|
-
self.layout().addWidget(self._onTheFlyQRB)
|
429
|
-
self._group.addButton(self._onTheFlyQRB)
|
430
|
-
|
431
|
-
name = FFCWhen.preprocessing.name.replace("_", " ")
|
432
|
-
self._preProcQRB = qt.QRadioButton(name, self)
|
433
|
-
self._preProcQRB.setToolTip(
|
434
|
-
"make flat field on a preprocessing step. "
|
435
|
-
"Can be interesting if you intend to test "
|
436
|
-
"several reconstruction parameters"
|
437
|
-
)
|
438
|
-
self.layout().addWidget(self._preProcQRB)
|
439
|
-
self._group.addButton(self._preProcQRB)
|
440
|
-
|
441
|
-
# setting: default on the fly
|
442
|
-
self._onTheFlyQRB.setChecked(True)
|
443
|
-
|
444
|
-
def getWhen(self):
|
445
|
-
if self._onTheFlyQRB.isChecked():
|
446
|
-
return FFCWhen.on_the_fly
|
447
|
-
elif self._preProcQRB.isChecked():
|
448
|
-
return FFCWhen.preprocessing
|
449
|
-
else:
|
450
|
-
raise ValueError('No "when" defined')
|
451
|
-
|
452
|
-
def setWhen(self, name):
|
453
|
-
if isinstance(name, FFCWhen):
|
454
|
-
if name is FFCWhen.on_the_fly:
|
455
|
-
self._onTheFlyQRB.setChecked(True)
|
456
|
-
elif name is FFCWhen.preprocessing:
|
457
|
-
self._preProcQRB.setChecked(True)
|
458
|
-
else:
|
459
|
-
raise ValueError("FFCWhen type is not managed")
|
460
|
-
elif type(name) is str:
|
461
|
-
try:
|
462
|
-
_name = name.split(".")[-1]
|
463
|
-
# name.split('.')[-1] because name can be given as FFCWhen.on_the_fly...
|
464
|
-
_when_instance = getattr(FFCWhen, _name.lower().replace(" ", "_"))
|
465
|
-
except Exception:
|
466
|
-
_logger.error(f"fail to determine 'FFCWhen' value from {name}")
|
467
|
-
else:
|
468
|
-
self.setWhen(_when_instance)
|
469
|
-
else:
|
470
|
-
raise ValueError("name should be a str or a FFCWhen")
|
471
|
-
|
472
|
-
def forcePreprocessing(self, force_):
|
473
|
-
old = self.blockSignals(True)
|
474
|
-
if force_:
|
475
|
-
self._preProcQRB.setChecked(True)
|
476
|
-
self.setEnabled(not force_)
|
477
|
-
self.blockSignals(old)
|
478
|
-
|
479
|
-
|
480
|
-
class CenteringTofuGroupBox(qt.QGroupBox):
|
481
|
-
"""
|
482
|
-
Widget used to display centering information
|
483
|
-
"""
|
484
|
-
|
485
|
-
def __init__(self, parent):
|
486
|
-
qt.QGroupBox.__init__(self, "centering", parent)
|
487
|
-
self.setLayout(qt.QGridLayout())
|
488
|
-
self.layout().addWidget(qt.QLabel("x center", parent=self), 0, 0)
|
489
|
-
self._xCenterLE = qt.QLineEdit("0", parent=self)
|
490
|
-
validator = qt.QDoubleValidator(parent=self)
|
491
|
-
self._xCenterLE.setValidator(validator)
|
492
|
-
self.layout().addWidget(self._xCenterLE, 0, 1)
|
493
|
-
|
494
|
-
self.layout().addWidget(qt.QLabel("y center", parent=self), 1, 0)
|
495
|
-
self._yCenterLE = qt.QLineEdit("0", parent=self)
|
496
|
-
self._yCenterLE.setValidator(validator)
|
497
|
-
self.layout().addWidget(self._yCenterLE, 1, 1)
|
498
|
-
|
499
|
-
self._lockButton = PadlockButton(parent=self)
|
500
|
-
self._lockButton.setSizePolicy(
|
501
|
-
qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding
|
502
|
-
)
|
503
|
-
self.layout().addWidget(self._lockButton, 0, 2, 2, 2)
|
504
|
-
|
505
|
-
# expose API
|
506
|
-
self.isLocked = self._lockButton.isLocked
|
507
|
-
|
508
|
-
def getXCenter(self):
|
509
|
-
return float(self._xCenterLE.text())
|
510
|
-
|
511
|
-
def setXCenter(self, value):
|
512
|
-
self._xCenterLE.setText(str(value))
|
513
|
-
|
514
|
-
def getZCenter(self):
|
515
|
-
return float(self._yCenterLE.text())
|
516
|
-
|
517
|
-
def setZCenter(self, value):
|
518
|
-
self._yCenterLE.setText(str(value))
|
519
|
-
|
520
|
-
def loadFromScan(self, scanID):
|
521
|
-
if self.isLocked() is False:
|
522
|
-
# can be set from Dim 1 and Dim 2
|
523
|
-
# question: here to avoid interpolation we simply make an integer
|
524
|
-
# division which give an integer
|
525
|
-
dim1, dim2 = getDim1Dim2(scanID)
|
526
|
-
for dim, lineEdit in zip((dim1, dim2), (self._xCenterLE, self._yCenterLE)):
|
527
|
-
if dim is not None:
|
528
|
-
lineEdit.setText(str(int(dim / 2)))
|
529
|
-
|
530
|
-
# try to set x center from the .par file
|
531
|
-
try:
|
532
|
-
parFile = os.path.join(scanID, os.path.basename(scanID) + ".par")
|
533
|
-
if os.path.exists(parFile) is True:
|
534
|
-
params = getParametersFromParOrInfo(parFile)
|
535
|
-
rot_axis_pos = None
|
536
|
-
for k in ("ROTATION_AXIS_POS", "ROTATION_AXIS_POSITION"):
|
537
|
-
if k.lower() in params:
|
538
|
-
rot_axis_pos = params[k.lower()]
|
539
|
-
|
540
|
-
if rot_axis_pos is not None:
|
541
|
-
self._xCenterLE.setText(str(rot_axis_pos))
|
542
|
-
except Exception as error:
|
543
|
-
_logger.error(error)
|
544
|
-
|
545
|
-
|
546
|
-
class NbFilesWidget(qt.QWidget):
|
547
|
-
"""
|
548
|
-
Widget to display the number of file (projection) to be send to tofu
|
549
|
-
"""
|
550
|
-
|
551
|
-
def __init__(self, parent=None):
|
552
|
-
qt.QWidget.__init__(self, parent=parent)
|
553
|
-
self.setLayout(qt.QGridLayout())
|
554
|
-
self.layout().addWidget(qt.QLabel("number of files", parent=self), 0, 0)
|
555
|
-
self._nFileLE = qt.QLineEdit("0", parent=self)
|
556
|
-
validator = qt.QIntValidator()
|
557
|
-
validator.setBottom(0)
|
558
|
-
self._nFileLE.setValidator(validator)
|
559
|
-
self.layout().addWidget(self._nFileLE, 0, 1)
|
560
|
-
|
561
|
-
def setNumberOfFiles(self, n):
|
562
|
-
self._nFileLE.setText(str(n))
|
563
|
-
|
564
|
-
def getNumberOfFiles(self):
|
565
|
-
if self._nFileLE.text().isdigit():
|
566
|
-
return int(self._nFileLE.text())
|
567
|
-
else:
|
568
|
-
return 0
|
569
|
-
|
570
|
-
|
571
|
-
class AngleIllustrations(qt.QWidget):
|
572
|
-
def __init__(self, parent):
|
573
|
-
qt.QWidget.__init__(self, parent)
|
574
|
-
self.setLayout(qt.QVBoxLayout())
|
575
|
-
self.setContentsMargins(0, 0, 0, 0)
|
576
|
-
self._infoLabel = qt.QLabel(parent=self)
|
577
|
-
icon = icons.getQIcon("information")
|
578
|
-
self._infoLabel.setPixmap(icon.pixmap(qt.QSize(32, 32)))
|
579
|
-
self.layout().addWidget(self._infoLabel)
|
580
|
-
|
581
|
-
self.illustrationCB = qt.QComboBox(parent=self)
|
582
|
-
self.illustrationCB.addItem("lamino angle")
|
583
|
-
self.illustrationCB.addItem(PSI_CHAR + " angle")
|
584
|
-
self.layout().addWidget(self.illustrationCB)
|
585
|
-
|
586
|
-
self._illustrations = qt.QWidget(parent=self)
|
587
|
-
self._illustrations.setLayout(qt.QHBoxLayout())
|
588
|
-
self.layout().addWidget(self._illustrations)
|
589
|
-
self._laminoAngleIllustration = _IllustrationWidget(
|
590
|
-
parent=self, img="lamino_angle"
|
591
|
-
)
|
592
|
-
self._psiAngleIllustration = _IllustrationWidget(parent=self, img="psi_angle")
|
593
|
-
self._illustrations.setMinimumSize(qt.QSize(200, 200))
|
594
|
-
self._illustrations.setSizePolicy(
|
595
|
-
qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding
|
596
|
-
)
|
597
|
-
|
598
|
-
self._illustrations.setContentsMargins(0, 0, 0, 0)
|
599
|
-
self._illustrations.layout().setSpacing(0)
|
600
|
-
self._illustrations.layout().addWidget(self._laminoAngleIllustration)
|
601
|
-
self._illustrations.layout().addWidget(self._psiAngleIllustration)
|
602
|
-
self.layout().addWidget(self._illustrations)
|
603
|
-
self.setActiveIllustration("lamino angle")
|
604
|
-
self.illustrationCB.currentIndexChanged[str].connect(self.setActiveIllustration)
|
605
|
-
|
606
|
-
def setActiveIllustration(self, name):
|
607
|
-
assert name in ("lamino angle", PSI_CHAR + " angle", THETA_CHAR + " angle")
|
608
|
-
if name == THETA_CHAR + " angle":
|
609
|
-
_logger.info("No illustration of the delta angle for the moment")
|
610
|
-
return
|
611
|
-
self.blockSignals(True)
|
612
|
-
index = self.illustrationCB.findText(name)
|
613
|
-
assert index >= 0
|
614
|
-
self.illustrationCB.setCurrentIndex(index)
|
615
|
-
|
616
|
-
self._laminoAngleIllustration.setVisible(name == "lamino angle")
|
617
|
-
self._psiAngleIllustration.setVisible(name == PSI_CHAR + " angle")
|
618
|
-
|
619
|
-
self.blockSignals(False)
|
620
|
-
|
621
|
-
|
622
|
-
class RotationAngleGroupBox(qt.QGroupBox):
|
623
|
-
def __init__(self, parent):
|
624
|
-
qt.QGroupBox.__init__(self, "angles", parent)
|
625
|
-
self.setLayout(qt.QHBoxLayout())
|
626
|
-
|
627
|
-
self.layout().setContentsMargins(0, 0, 0, 0)
|
628
|
-
self.layout().setSpacing(0)
|
629
|
-
|
630
|
-
self._angles = qt.QWidget(parent=self)
|
631
|
-
self._angles.setLayout(qt.QVBoxLayout())
|
632
|
-
self._angles.setContentsMargins(0, 0, 0, 0)
|
633
|
-
self.layout().addWidget(self._angles)
|
634
|
-
|
635
|
-
self._laminoAngle = _AngleWidget(
|
636
|
-
parent=self._angles,
|
637
|
-
name="rotation axis tilt",
|
638
|
-
defaultVal=90,
|
639
|
-
lockable=True,
|
640
|
-
information=self._showLaminoAngleInfo,
|
641
|
-
)
|
642
|
-
self._angles.layout().addWidget(self._laminoAngle)
|
643
|
-
self._axisAngleY = _AngleWidget(
|
644
|
-
parent=self._angles,
|
645
|
-
name=(PSI_CHAR + " angle"),
|
646
|
-
lockable=True,
|
647
|
-
information=self._showPsiAngleInfo,
|
648
|
-
)
|
649
|
-
self._angles.layout().addWidget(self._axisAngleY)
|
650
|
-
|
651
|
-
self._axisAngleZ = _AngleWidget(
|
652
|
-
parent=self._angles, name=(THETA_CHAR + " angle"), lockable=True
|
653
|
-
)
|
654
|
-
self._angles.layout().addWidget(self._axisAngleZ)
|
655
|
-
self._axisAngleZ.setVisible(False)
|
656
|
-
|
657
|
-
self._overallAngle = _AngleWidget(
|
658
|
-
parent=self, name="overall angle", defaultVal=360, lockable=True
|
659
|
-
)
|
660
|
-
self._angles.layout().addWidget(self._overallAngle)
|
661
|
-
|
662
|
-
self._spacer = qt.QWidget(parent=self._angles)
|
663
|
-
self._spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
|
664
|
-
self._angles.layout().addWidget(self._spacer)
|
665
|
-
|
666
|
-
self._infoLamino = None
|
667
|
-
self._infoPsi = None
|
668
|
-
|
669
|
-
# expose some API
|
670
|
-
self.getLaminoAngle = self._laminoAngle.getAngle
|
671
|
-
self.getPsiAngle = self._axisAngleY.getAngle
|
672
|
-
|
673
|
-
def _showLaminoAngleInfo(self):
|
674
|
-
self.getInfoLaminoDialog().show()
|
675
|
-
self.getInfoLaminoDialog().raise_()
|
676
|
-
self.getInfoLaminoDialog().activateWindow()
|
677
|
-
|
678
|
-
def _showPsiAngleInfo(self):
|
679
|
-
self.getPsiLaminoDialog().show()
|
680
|
-
self.getPsiLaminoDialog().raise_()
|
681
|
-
self.getPsiLaminoDialog().activateWindow()
|
682
|
-
|
683
|
-
def getInfoLaminoDialog(self):
|
684
|
-
if self._infoLamino is None:
|
685
|
-
self._infoLamino = _IllustrationDialog(
|
686
|
-
parent=self, img="lamino_angle", title="information about lamino angle"
|
687
|
-
)
|
688
|
-
return self._infoLamino
|
689
|
-
|
690
|
-
def getPsiLaminoDialog(self):
|
691
|
-
if self._infoPsi is None:
|
692
|
-
self._infoPsi = _IllustrationDialog(
|
693
|
-
parent=self,
|
694
|
-
img="psi_angle",
|
695
|
-
title=" ".join(("information about", PSI_CHAR, "angle")),
|
696
|
-
)
|
697
|
-
return self._infoPsi
|
698
|
-
|
699
|
-
def loadFromScan(self, scanID):
|
700
|
-
assert type(scanID) is str
|
701
|
-
_info_file = os.path.join(scanID, os.path.basename(scanID) + ".info")
|
702
|
-
if os.path.isfile(_info_file) is True:
|
703
|
-
info = getParametersFromParOrInfo(_info_file)
|
704
|
-
if self._laminoAngle.isLocked() is False and "ctangle" in info:
|
705
|
-
self._laminoAngle.setAngle(90.0 - float(info["ctangle"]))
|
706
|
-
if self._overallAngle.isLocked() is False and "scanrange" in info:
|
707
|
-
self._overallAngle.setAngle(float(info["scanrange"]))
|
708
|
-
|
709
|
-
def _setOverallAngleI(self, val):
|
710
|
-
"""
|
711
|
-
Set the inverse value to the lamino angle
|
712
|
-
|
713
|
-
:param val:
|
714
|
-
:return:
|
715
|
-
"""
|
716
|
-
_val = float(val) * -1.0
|
717
|
-
self._overallAngle.setAngle(_val)
|
718
|
-
|
719
|
-
|
720
|
-
class PhaseRetrievalWidget(_TofuOptionLoader, qt.QGroupBox):
|
721
|
-
"""
|
722
|
-
Widget sued to defined the phase retrieval
|
723
|
-
"""
|
724
|
-
|
725
|
-
activated = qt.Signal()
|
726
|
-
"""Emitted when the phase retrieval is activated"""
|
727
|
-
|
728
|
-
METHODS = "tie", "ctf", "ctfhalfsin", "qp", "qphalfsine", "qp2"
|
729
|
-
DEFAULT_METHOD = "tie"
|
730
|
-
|
731
|
-
def __init__(self, parent):
|
732
|
-
qt.QGroupBox.__init__(self, "phase retrieval (*)", parent)
|
733
|
-
self.setToolTip("Activating phase retrieval will deactivate " "absorptivity")
|
734
|
-
self.setLayout(qt.QGridLayout())
|
735
|
-
# retrieval method
|
736
|
-
self._retrievalMethodCB = qt.QComboBox(parent=self)
|
737
|
-
for _method in self.METHODS:
|
738
|
-
self._retrievalMethodCB.addItem(_method)
|
739
|
-
assert self.DEFAULT_METHOD in self.METHODS
|
740
|
-
self._retrievalMethodCB.setCurrentIndex(
|
741
|
-
self._retrievalMethodCB.findText(self.DEFAULT_METHOD)
|
742
|
-
)
|
743
|
-
self.layout().addWidget(qt.QLabel("retrieval method:", self), 0, 0)
|
744
|
-
self.layout().addWidget(self._retrievalMethodCB, 0, 1)
|
745
|
-
|
746
|
-
# energy
|
747
|
-
self.layout().addWidget(qt.QLabel("energy:", self), 1, 0)
|
748
|
-
self._energy = qt.QLineEdit("65.0", parent=self)
|
749
|
-
validator = qt.QDoubleValidator(parent=self._energy)
|
750
|
-
self._energy.setValidator(validator)
|
751
|
-
self.layout().addWidget(self._energy, 1, 1)
|
752
|
-
self._energyLockButton = PadlockButton(parent=self)
|
753
|
-
self.layout().addWidget(self._energyLockButton, 1, 2)
|
754
|
-
|
755
|
-
# regularization rate
|
756
|
-
self.layout().addWidget(qt.QLabel("regularization rate:", self), 3, 0)
|
757
|
-
self._regularizationRate = qt.QLineEdit("1.5", parent=self)
|
758
|
-
validator = qt.QDoubleValidator(parent=self._regularizationRate)
|
759
|
-
self._regularizationRate.setValidator(validator)
|
760
|
-
self.layout().addWidget(self._regularizationRate, 3, 1)
|
761
|
-
self._regRateLockButton = PadlockButton(parent=self)
|
762
|
-
self.layout().addWidget(self._regRateLockButton, 3, 2)
|
763
|
-
|
764
|
-
# thresholding rate
|
765
|
-
self.layout().addWidget(qt.QLabel("thresholding rate:", self), 4, 0)
|
766
|
-
self._thresholdingRate = qt.QLineEdit("0.4", parent=self)
|
767
|
-
validator = qt.QDoubleValidator(parent=self._thresholdingRate)
|
768
|
-
self._thresholdingRate.setValidator(validator)
|
769
|
-
self.layout().addWidget(self._thresholdingRate, 4, 1)
|
770
|
-
|
771
|
-
# propagation distance
|
772
|
-
self.layout().addWidget(qt.QLabel("propagation distance (m):", self), 5, 0)
|
773
|
-
self._propagationDistance = qt.QLineEdit("0.08", parent=self)
|
774
|
-
validator = qt.QDoubleValidator(parent=self._propagationDistance)
|
775
|
-
self._propagationDistance.setValidator(validator)
|
776
|
-
self.layout().addWidget(self._propagationDistance, 5, 1)
|
777
|
-
self._propaDistLockButton = PadlockButton(parent=self)
|
778
|
-
self.layout().addWidget(self._propaDistLockButton, 5, 2)
|
779
|
-
|
780
|
-
# create some more speaking API
|
781
|
-
self.energyIsLocked = self._energyLockButton.isLocked
|
782
|
-
self.getRetrievalMethod = self._retrievalMethodCB.currentText
|
783
|
-
self.propaDistIsLocked = self._propaDistLockButton.isLocked
|
784
|
-
|
785
|
-
# signal/slot connection
|
786
|
-
self.toggled.connect(self.__toggleCallback)
|
787
|
-
|
788
|
-
options = {
|
789
|
-
"retrieval-method": _getterSetter(
|
790
|
-
getter=self._getRetrievalMethod, setter=self.setRetrievalMethod
|
791
|
-
),
|
792
|
-
"energy": _getterSetter(getter=self._getEnergy, setter=self.setEnergy),
|
793
|
-
"propagation-distance": _getterSetter(
|
794
|
-
getter=self._getPropagationDistance, setter=self.setPropagationDistance
|
795
|
-
),
|
796
|
-
"regularization-rate": _getterSetter(
|
797
|
-
getter=self._getRegularizationRate, setter=self.setRegularizationRate
|
798
|
-
),
|
799
|
-
"thresholding-rate": _getterSetter(
|
800
|
-
getter=self._getThresholdingRate, setter=self.setThresholdingRate
|
801
|
-
),
|
802
|
-
}
|
803
|
-
_TofuOptionLoader.__init__(self, options=options)
|
804
|
-
|
805
|
-
def loadFromScan(self, scanID):
|
806
|
-
_info_file = os.path.join(scanID, os.path.basename(scanID) + ".info")
|
807
|
-
if os.path.isfile(_info_file) is True:
|
808
|
-
energy = getClosestEnergy(scanID)
|
809
|
-
if energy is not None and self.energyIsLocked() is False:
|
810
|
-
self.setEnergy(energy)
|
811
|
-
info = getParametersFromParOrInfo(_info_file)
|
812
|
-
if "distance" in info and self.propaDistIsLocked() is False:
|
813
|
-
try:
|
814
|
-
dst = float(info["distance"])
|
815
|
-
# convert to meter
|
816
|
-
dst = dst / 1000.0
|
817
|
-
self.setPropagationDistance(dst)
|
818
|
-
except Exception:
|
819
|
-
pass
|
820
|
-
|
821
|
-
def setUnchecked(self):
|
822
|
-
self.setChecked(False)
|
823
|
-
|
824
|
-
def __toggleCallback(self, checked):
|
825
|
-
if checked is True:
|
826
|
-
self.activated.emit()
|
827
|
-
|
828
|
-
# retrieval method
|
829
|
-
def _getRetrievalMethod(self):
|
830
|
-
if self.isChecked() is True:
|
831
|
-
return self.getRetrievalMethod()
|
832
|
-
else:
|
833
|
-
return None
|
834
|
-
|
835
|
-
def setRetrievalMethod(self, method):
|
836
|
-
if method is not None:
|
837
|
-
if method not in self.METHODS:
|
838
|
-
_logger.error("method %s is not recognized as a retrieval " "method")
|
839
|
-
else:
|
840
|
-
index = self._retrievalMethodCB.find(method)
|
841
|
-
self._retrievalMethodCB.setCurrentIndex(index)
|
842
|
-
|
843
|
-
# energy
|
844
|
-
def getEnergy(self):
|
845
|
-
return float(self._energy.text())
|
846
|
-
|
847
|
-
def _getEnergy(self):
|
848
|
-
"Return None if not activated, otherwise the value"
|
849
|
-
if self.isChecked() is True:
|
850
|
-
return self.getEnergy()
|
851
|
-
|
852
|
-
def setEnergy(self, energy):
|
853
|
-
if energy is not None:
|
854
|
-
self._energy.setText(str(energy))
|
855
|
-
|
856
|
-
# propagation distance
|
857
|
-
def getPropagationDistance(self):
|
858
|
-
return float(self._propagationDistance.text())
|
859
|
-
|
860
|
-
def _getPropagationDistance(self):
|
861
|
-
if self.isChecked() is True:
|
862
|
-
return self.getPropagationDistance()
|
863
|
-
else:
|
864
|
-
return None
|
865
|
-
|
866
|
-
def setPropagationDistance(self, distance):
|
867
|
-
if distance is not None:
|
868
|
-
self._propagationDistance.setText(str(distance))
|
869
|
-
|
870
|
-
# regularization rate
|
871
|
-
def getRegularizationRate(self):
|
872
|
-
return float(self._regularizationRate.text())
|
873
|
-
|
874
|
-
def _getRegularizationRate(self):
|
875
|
-
if self.isChecked() is True:
|
876
|
-
return self.getRegularizationRate()
|
877
|
-
else:
|
878
|
-
return None
|
879
|
-
|
880
|
-
def setRegularizationRate(self, rate):
|
881
|
-
if rate is not None:
|
882
|
-
self._regularizationRate.setText(str(rate))
|
883
|
-
|
884
|
-
# thresholding rate
|
885
|
-
def getThresholdingRate(self):
|
886
|
-
return float(self._thresholdingRate.text())
|
887
|
-
|
888
|
-
def _getThresholdingRate(self):
|
889
|
-
if self.isChecked() is True:
|
890
|
-
return self.getThresholdingRate()
|
891
|
-
else:
|
892
|
-
return None
|
893
|
-
|
894
|
-
def setThresholdingRate(self, rate):
|
895
|
-
if rate is not None:
|
896
|
-
self._thresholdingRate.setText(str(rate))
|