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
@@ -0,0 +1,534 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# /*##########################################################################
|
3
|
+
# Copyright (C) 2016 European Synchrotron Radiation Facility
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
#
|
23
|
+
#############################################################################*/
|
24
|
+
|
25
|
+
|
26
|
+
__authors__ = ["H.Payno"]
|
27
|
+
__license__ = "MIT"
|
28
|
+
__date__ = "09/08/2018"
|
29
|
+
|
30
|
+
|
31
|
+
import functools
|
32
|
+
import io
|
33
|
+
import json
|
34
|
+
import logging
|
35
|
+
import os
|
36
|
+
import pathlib
|
37
|
+
from datetime import datetime
|
38
|
+
from typing import Optional
|
39
|
+
from urllib.parse import urlparse
|
40
|
+
|
41
|
+
import h5py
|
42
|
+
from processview.core.dataset import DatasetIdentifier
|
43
|
+
from silx.io.utils import open as open_hdf5
|
44
|
+
from tomoscan.esrf.identifier.hdf5Identifier import (
|
45
|
+
NXtomoScanIdentifier as _NXtomoScanIdentifier,
|
46
|
+
)
|
47
|
+
from tomoscan.esrf.identifier.url_utils import UrlSettings, split_path, split_query
|
48
|
+
from tomoscan.esrf.scan.nxtomoscan import NXtomoScan as _tsNXtomoScan
|
49
|
+
from nxtomo.nxobject.nxdetector import ImageKey
|
50
|
+
|
51
|
+
from tomwer.utils import docstring
|
52
|
+
from tomwer.core.scan.helicalmetadata import HelicalMetadata
|
53
|
+
|
54
|
+
from .scanbase import TomwerScanBase
|
55
|
+
|
56
|
+
_logger = logging.getLogger(__name__)
|
57
|
+
|
58
|
+
|
59
|
+
class NXtomoScanIdentifier(_NXtomoScanIdentifier, DatasetIdentifier):
|
60
|
+
def __init__(self, metadata=None, *args, **kwargs):
|
61
|
+
super().__init__(*args, **kwargs)
|
62
|
+
DatasetIdentifier.__init__(
|
63
|
+
self, data_builder=NXtomoScan.from_identifier, metadata=metadata
|
64
|
+
)
|
65
|
+
|
66
|
+
@staticmethod
|
67
|
+
def from_str(identifier):
|
68
|
+
info = urlparse(identifier)
|
69
|
+
paths = split_path(info.path)
|
70
|
+
if len(paths) == 1:
|
71
|
+
hdf5_file = paths[0]
|
72
|
+
tomo_type = None
|
73
|
+
elif len(paths) == 2:
|
74
|
+
tomo_type, hdf5_file = paths
|
75
|
+
else:
|
76
|
+
raise ValueError("Failed to parse path string:", info.path)
|
77
|
+
if tomo_type is not None and tomo_type != NXtomoScanIdentifier.TOMO_TYPE:
|
78
|
+
raise TypeError(
|
79
|
+
f"provided identifier fits {tomo_type} and not {NXtomoScanIdentifier.TOMO_TYPE}"
|
80
|
+
)
|
81
|
+
|
82
|
+
queries = split_query(info.query)
|
83
|
+
entry = queries.get(UrlSettings.DATA_PATH_KEY, None)
|
84
|
+
if entry is None:
|
85
|
+
raise ValueError(f"expects to get {UrlSettings.DATA_PATH_KEY} query")
|
86
|
+
|
87
|
+
return NXtomoScanIdentifier(object=NXtomoScan, hdf5_file=hdf5_file, entry=entry)
|
88
|
+
|
89
|
+
def long_description(self) -> str:
|
90
|
+
"""used for processview header tooltip for now"""
|
91
|
+
return self.to_str()
|
92
|
+
|
93
|
+
def short_description(self) -> str:
|
94
|
+
return f"scan: {self.data_path.lstrip('/')}@{os.path.basename(self._file_path)}"
|
95
|
+
|
96
|
+
|
97
|
+
class NXtomoScan(_tsNXtomoScan, TomwerScanBase):
|
98
|
+
"""
|
99
|
+
This is the implementation of a TomoBase class for an acquisition stored
|
100
|
+
in a HDF5 file.
|
101
|
+
|
102
|
+
For now several property of the acquisition is accessible thought a getter
|
103
|
+
(like get_scan_range) and a property (scan_range).
|
104
|
+
|
105
|
+
This is done to be compliant with TomoBase instanciation. But his will be
|
106
|
+
replace progressively by properties at the 'TomoBase' level
|
107
|
+
|
108
|
+
:param scan: scan directory or scan masterfile.h5
|
109
|
+
:type: Union[str,None]
|
110
|
+
"""
|
111
|
+
|
112
|
+
_TYPE = "hdf5"
|
113
|
+
|
114
|
+
def __init__(self, scan, entry, index=None, overwrite_proc_file=False):
|
115
|
+
TomwerScanBase.__init__(self)
|
116
|
+
_tsNXtomoScan.__init__(self, scan=scan, entry=entry, index=index)
|
117
|
+
# speed up for now, avoid to run check by default
|
118
|
+
self.set_check_behavior(run_check=False)
|
119
|
+
# register at least the 'default' working directory as a possible reconstruction path
|
120
|
+
self.add_reconstruction_path(self.path)
|
121
|
+
self._helical = HelicalMetadata()
|
122
|
+
|
123
|
+
self._reconstruction_urls = None
|
124
|
+
self._projections_with_angles = None
|
125
|
+
self._process_file = self.get_process_file_name(self)
|
126
|
+
self._init_index_process_file(overwrite_proc_file=overwrite_proc_file)
|
127
|
+
try:
|
128
|
+
reduced_darks, metadata = self.load_reduced_darks(return_info=True)
|
129
|
+
except (KeyError, OSError, ValueError):
|
130
|
+
# file or key does not exists
|
131
|
+
pass
|
132
|
+
else:
|
133
|
+
self.set_reduced_darks(reduced_darks, darks_infos=metadata)
|
134
|
+
|
135
|
+
try:
|
136
|
+
reduced_flats, metadata = self.load_reduced_flats(return_info=True)
|
137
|
+
except (KeyError, OSError, ValueError):
|
138
|
+
pass
|
139
|
+
else:
|
140
|
+
self.set_reduced_flats(reduced_flats, flats_infos=metadata)
|
141
|
+
|
142
|
+
@property
|
143
|
+
def working_directory(self):
|
144
|
+
if self.master_file is None:
|
145
|
+
return None
|
146
|
+
else:
|
147
|
+
return os.path.abspath(os.path.dirname(self.master_file))
|
148
|
+
|
149
|
+
@property
|
150
|
+
def helical(self):
|
151
|
+
return self._helical
|
152
|
+
|
153
|
+
@staticmethod
|
154
|
+
def from_identifier(identifier):
|
155
|
+
"""Return the Dataset from a identifier"""
|
156
|
+
if not isinstance(identifier, NXtomoScanIdentifier):
|
157
|
+
raise TypeError(
|
158
|
+
f"identifier should be an instance of {NXtomoScanIdentifier}. Not {type(identifier)}"
|
159
|
+
)
|
160
|
+
return NXtomoScan(scan=identifier.file_path, entry=identifier.data_path)
|
161
|
+
|
162
|
+
def get_identifier(self):
|
163
|
+
try:
|
164
|
+
stat = pathlib.Path(self.master_file).stat()
|
165
|
+
except Exception:
|
166
|
+
stat = None
|
167
|
+
|
168
|
+
return NXtomoScanIdentifier(
|
169
|
+
object=self,
|
170
|
+
hdf5_file=self.master_file,
|
171
|
+
entry=self.entry,
|
172
|
+
metadata={
|
173
|
+
"name": self.master_file,
|
174
|
+
"creation_time": (
|
175
|
+
datetime.fromtimestamp(stat.st_ctime) if stat else None
|
176
|
+
),
|
177
|
+
"modification_time": (
|
178
|
+
datetime.fromtimestamp(stat.st_ctime) if stat else None
|
179
|
+
),
|
180
|
+
},
|
181
|
+
)
|
182
|
+
|
183
|
+
@staticmethod
|
184
|
+
def get_process_file_name(scan):
|
185
|
+
if scan.path is not None:
|
186
|
+
basename, _ = os.path.splitext(scan.master_file)
|
187
|
+
basename = os.path.basename(basename)
|
188
|
+
basename = "_".join((basename, "tomwer_processes.h5"))
|
189
|
+
return os.path.join(scan.path, basename)
|
190
|
+
else:
|
191
|
+
return None
|
192
|
+
|
193
|
+
@staticmethod
|
194
|
+
def directory_contains_scan(directory, src_pattern=None, dest_pattern=None):
|
195
|
+
"""
|
196
|
+
|
197
|
+
Check if the given directory is holding an acquisition
|
198
|
+
|
199
|
+
:param str directory: directory we want to check
|
200
|
+
:param str src_pattern: buffer name pattern ('lbsram')
|
201
|
+
:param dest_pattern: output pattern (''). Needed because some
|
202
|
+
acquisition can split the file produce between
|
203
|
+
two directories. This is the case for edf,
|
204
|
+
where .info file are generated in /data/dir
|
205
|
+
instead of /lbsram/data/dir
|
206
|
+
:type: str
|
207
|
+
:return: does the given directory contains any acquisition
|
208
|
+
:rtype: bool
|
209
|
+
"""
|
210
|
+
master_file = os.path.join(directory, os.path.basename(directory))
|
211
|
+
if os.path.exists("master_file.hdf5"):
|
212
|
+
return True
|
213
|
+
else:
|
214
|
+
return os.path.exists(master_file + ".h5")
|
215
|
+
|
216
|
+
def clear_caches(self):
|
217
|
+
_tsNXtomoScan.clear_caches(self)
|
218
|
+
TomwerScanBase.clear_caches(self)
|
219
|
+
|
220
|
+
def is_abort(self, src_pattern, dest_pattern):
|
221
|
+
"""
|
222
|
+
Check if the acquisition have been aborted. In this case the directory
|
223
|
+
should contain a [scan].abo file
|
224
|
+
|
225
|
+
:param str src_pattern: buffer name pattern ('lbsram')
|
226
|
+
:param dest_pattern: output pattern (''). Needed because some
|
227
|
+
acquisition can split the file produce between
|
228
|
+
two directories. This is the case for edf,
|
229
|
+
where .info file are generated in /data/dir
|
230
|
+
instead of /lbsram/data/dir
|
231
|
+
:return: True if the acquisition have been abort and the directory
|
232
|
+
should be abort
|
233
|
+
"""
|
234
|
+
# for now there is no abort definition in .hdf5
|
235
|
+
return False
|
236
|
+
|
237
|
+
@staticmethod
|
238
|
+
def from_dict(_dict):
|
239
|
+
path = _dict[NXtomoScan.DICT_PATH_KEY]
|
240
|
+
entry = _dict[NXtomoScan._DICT_ENTRY_KEY]
|
241
|
+
|
242
|
+
scan = NXtomoScan(scan=path, entry=entry)
|
243
|
+
scan.load_from_dict(_dict=_dict)
|
244
|
+
return scan
|
245
|
+
|
246
|
+
@docstring(TomwerScanBase)
|
247
|
+
def load_from_dict(self, _dict):
|
248
|
+
"""
|
249
|
+
|
250
|
+
:param _dict:
|
251
|
+
:return:
|
252
|
+
"""
|
253
|
+
if isinstance(_dict, io.TextIOWrapper):
|
254
|
+
data = json.load(_dict)
|
255
|
+
else:
|
256
|
+
data = _dict
|
257
|
+
if not (self.DICT_TYPE_KEY in data and data[self.DICT_TYPE_KEY] == self._TYPE):
|
258
|
+
raise ValueError("Description is not an EDFScan json description")
|
259
|
+
|
260
|
+
_tsNXtomoScan.load_from_dict(self, _dict)
|
261
|
+
TomwerScanBase.load_from_dict(self, _dict)
|
262
|
+
return self
|
263
|
+
|
264
|
+
@docstring(TomwerScanBase)
|
265
|
+
def to_dict(self) -> dict:
|
266
|
+
ddict = _tsNXtomoScan.to_dict(self)
|
267
|
+
ddict.update(TomwerScanBase.to_dict(self))
|
268
|
+
return ddict
|
269
|
+
|
270
|
+
def update(self):
|
271
|
+
"""update list of radio and reconstruction by parsing the scan folder"""
|
272
|
+
if self.master_file is None:
|
273
|
+
return
|
274
|
+
if not os.path.exists(self.master_file):
|
275
|
+
return
|
276
|
+
_tsNXtomoScan.update(self)
|
277
|
+
self.reconstructions = self.get_reconstructions_urls()
|
278
|
+
|
279
|
+
def _get_scheme(self):
|
280
|
+
"""
|
281
|
+
|
282
|
+
:return: scheme to read url
|
283
|
+
:rtype: str
|
284
|
+
"""
|
285
|
+
return "silx"
|
286
|
+
|
287
|
+
def is_finish(self):
|
288
|
+
return len(self.projections) >= self.tomo_n
|
289
|
+
|
290
|
+
@docstring(TomwerScanBase.get_sinogram)
|
291
|
+
@functools.lru_cache(maxsize=16, typed=True)
|
292
|
+
def get_sinogram(self, line, subsampling=1, norm_method=None, **kwargs):
|
293
|
+
"""
|
294
|
+
|
295
|
+
extract the sinogram from projections
|
296
|
+
|
297
|
+
:param line: which sinogram we want
|
298
|
+
:type: int
|
299
|
+
:param subsampling: subsampling to apply if any. Allows to skip some io
|
300
|
+
:type: int
|
301
|
+
:return: sinogram from the radio lines
|
302
|
+
:rtype: numpy.array
|
303
|
+
"""
|
304
|
+
return _tsNXtomoScan.get_sinogram(
|
305
|
+
self,
|
306
|
+
line=line,
|
307
|
+
subsampling=subsampling,
|
308
|
+
norm_method=norm_method,
|
309
|
+
**kwargs,
|
310
|
+
)
|
311
|
+
|
312
|
+
@docstring(TomwerScanBase.get_proj_angle_url)
|
313
|
+
def get_proj_angle_url(self, use_cache: bool = True, with_alignment=True):
|
314
|
+
if not use_cache:
|
315
|
+
self._cache_proj_urls = None
|
316
|
+
|
317
|
+
if self._cache_proj_urls is None:
|
318
|
+
frames = self.frames
|
319
|
+
if frames is None:
|
320
|
+
return {}
|
321
|
+
|
322
|
+
self._cache_proj_urls = {}
|
323
|
+
for frame in frames:
|
324
|
+
if frame.image_key is ImageKey.PROJECTION:
|
325
|
+
if frame.is_control and with_alignment:
|
326
|
+
self._cache_proj_urls[f"{frame.rotation_angle} (1)"] = frame.url
|
327
|
+
elif frame.is_control:
|
328
|
+
continue
|
329
|
+
else:
|
330
|
+
self._cache_proj_urls[str(frame.rotation_angle)] = frame.url
|
331
|
+
return self._cache_proj_urls
|
332
|
+
|
333
|
+
@docstring(TomwerScanBase._deduce_transfert_scan)
|
334
|
+
def _deduce_transfert_scan(self, output_dir):
|
335
|
+
new_master_file_path = os.path.join(
|
336
|
+
output_dir, os.path.basename(self.master_file)
|
337
|
+
)
|
338
|
+
return NXtomoScan(scan=new_master_file_path, entry=self.entry)
|
339
|
+
|
340
|
+
def data_flat_field_correction(self, data, index=None):
|
341
|
+
flats = self.reduced_flats
|
342
|
+
flat1 = flat2 = None
|
343
|
+
index_flat1 = index_flat2 = None
|
344
|
+
if flats is not None:
|
345
|
+
flat_indexes = sorted(list(flats.keys()))
|
346
|
+
if len(flats) > 0:
|
347
|
+
index_flat1 = flat_indexes[0]
|
348
|
+
flat1 = flats[index_flat1]
|
349
|
+
if len(flats) > 1:
|
350
|
+
index_flat2 = flat_indexes[-1]
|
351
|
+
flat2 = flats[index_flat2]
|
352
|
+
darks = self.reduced_darks
|
353
|
+
dark = None
|
354
|
+
if darks is not None and len(darks) > 0:
|
355
|
+
# take only one dark into account for now
|
356
|
+
dark = list(darks.values())[0]
|
357
|
+
return self._flat_field_correction(
|
358
|
+
data=data,
|
359
|
+
dark=dark,
|
360
|
+
flat1=flat1,
|
361
|
+
flat2=flat2,
|
362
|
+
index_flat1=index_flat1,
|
363
|
+
index_flat2=index_flat2,
|
364
|
+
index_proj=index,
|
365
|
+
)
|
366
|
+
|
367
|
+
@docstring(_tsNXtomoScan.ff_interval)
|
368
|
+
@property
|
369
|
+
def ff_interval(self):
|
370
|
+
"""
|
371
|
+
Make some assumption to compute the flat field interval:
|
372
|
+
"""
|
373
|
+
|
374
|
+
def get_first_two_ff_indexes():
|
375
|
+
if self.flats is None:
|
376
|
+
return None, None
|
377
|
+
else:
|
378
|
+
self._last_flat_index = None
|
379
|
+
self._first_serie_flat_index = None
|
380
|
+
for flat_index in self.flats:
|
381
|
+
if self._last_flat_index is None:
|
382
|
+
self._last_flat_index = flat_index
|
383
|
+
elif flat_index == self._last_flat_index + 1:
|
384
|
+
self._last_flat_index = flat_index
|
385
|
+
continue
|
386
|
+
else:
|
387
|
+
return self._last_flat_index, flat_index
|
388
|
+
return None, None
|
389
|
+
|
390
|
+
first_serie_index, second_serie_index = get_first_two_ff_indexes()
|
391
|
+
if first_serie_index is None:
|
392
|
+
return 0
|
393
|
+
elif second_serie_index is not None:
|
394
|
+
return second_serie_index - first_serie_index - 1
|
395
|
+
else:
|
396
|
+
return 0
|
397
|
+
|
398
|
+
def projections_with_angle(self):
|
399
|
+
"""projections / radio, does not include the return projections"""
|
400
|
+
if self._projections_with_angles is None:
|
401
|
+
if self.frames:
|
402
|
+
proj_frames = tuple(
|
403
|
+
filter(
|
404
|
+
lambda x: x.image_key == ImageKey.PROJECTION
|
405
|
+
and x.is_control is False,
|
406
|
+
self.frames,
|
407
|
+
)
|
408
|
+
)
|
409
|
+
self._projections_with_angles = {}
|
410
|
+
for proj_frame in proj_frames:
|
411
|
+
self._projections_with_angles[proj_frame.rotation_angle] = (
|
412
|
+
proj_frame.url
|
413
|
+
)
|
414
|
+
return self._projections_with_angles
|
415
|
+
|
416
|
+
@staticmethod
|
417
|
+
def is_nexus_nxtomo_file(file_path: str) -> bool:
|
418
|
+
if h5py.is_hdf5(file_path):
|
419
|
+
return len(NXtomoScan.get_nxtomo_entries(file_path)) > 0
|
420
|
+
|
421
|
+
@staticmethod
|
422
|
+
def get_nxtomo_entries(file_path: str) -> tuple:
|
423
|
+
if not h5py.is_hdf5(file_path):
|
424
|
+
return tuple()
|
425
|
+
else:
|
426
|
+
res = []
|
427
|
+
with open_hdf5(file_path) as h5s:
|
428
|
+
for entry_name, node in h5s.items():
|
429
|
+
if isinstance(node, h5py.Group):
|
430
|
+
if NXtomoScan.entry_is_nx_tomo(node):
|
431
|
+
res.append(entry_name)
|
432
|
+
return tuple(res)
|
433
|
+
|
434
|
+
@staticmethod
|
435
|
+
def entry_is_nx_tomo(entry: h5py.Group):
|
436
|
+
return ("beam" in entry and "instrument" in entry and "sample" in entry) or (
|
437
|
+
hasattr(entry, "attrs")
|
438
|
+
and "definition" in entry.attrs
|
439
|
+
and entry.attrs["definition"] == "NXtomo"
|
440
|
+
)
|
441
|
+
|
442
|
+
@staticmethod
|
443
|
+
def is_nxdetector(grp: h5py.Group):
|
444
|
+
"""
|
445
|
+
Check if the grp is an nx detector
|
446
|
+
|
447
|
+
:param h5py.Group grp:
|
448
|
+
:return: True if this is the definition of a group
|
449
|
+
:rtype: bool
|
450
|
+
"""
|
451
|
+
if hasattr(grp, "attrs"):
|
452
|
+
if "NX_class" in grp.attrs and grp.attrs["NX_class"] == "NXdetector":
|
453
|
+
return True
|
454
|
+
return False
|
455
|
+
|
456
|
+
# Dataset implementation
|
457
|
+
|
458
|
+
@docstring(TomwerScanBase)
|
459
|
+
def get_nabu_dataset_info(self, binning=1, binning_z=1, proj_subsampling=1):
|
460
|
+
if not isinstance(binning, int):
|
461
|
+
raise TypeError(f"binning should be an int. Not {type(binning)}")
|
462
|
+
if not isinstance(binning_z, int):
|
463
|
+
raise TypeError(f"binning_z should be an int. Not {type(binning_z)}")
|
464
|
+
if not isinstance(proj_subsampling, int):
|
465
|
+
raise TypeError(
|
466
|
+
f"proj_subsampling should be an int. Not {type(proj_subsampling)}"
|
467
|
+
)
|
468
|
+
return {
|
469
|
+
"hdf5_entry": self.entry,
|
470
|
+
"location": os.path.basename(self.master_file),
|
471
|
+
"binning": binning,
|
472
|
+
"binning_z": binning_z,
|
473
|
+
"projections_subsampling": proj_subsampling,
|
474
|
+
}
|
475
|
+
|
476
|
+
@docstring(TomwerScanBase)
|
477
|
+
def to_nabu_dataset_analyser(self):
|
478
|
+
from nabu.resources.dataset_analyzer import HDF5DatasetAnalyzer
|
479
|
+
|
480
|
+
return HDF5DatasetAnalyzer(
|
481
|
+
location=self.master_file, extra_options={"hdf5_entry": self.entry}
|
482
|
+
)
|
483
|
+
|
484
|
+
@docstring(TomwerScanBase)
|
485
|
+
def scan_dir_name(self) -> Optional[str]:
|
486
|
+
"""for 'this/is/my/file.h5' returns 'my'"""
|
487
|
+
if self.master_file is not None:
|
488
|
+
return os.path.dirname(self.master_file).split(os.sep)[-1]
|
489
|
+
else:
|
490
|
+
return None
|
491
|
+
|
492
|
+
@docstring(TomwerScanBase)
|
493
|
+
def scan_basename(self):
|
494
|
+
if self.master_file is not None:
|
495
|
+
try:
|
496
|
+
return os.path.dirname(self.master_file)
|
497
|
+
except Exception:
|
498
|
+
return None
|
499
|
+
else:
|
500
|
+
return None
|
501
|
+
|
502
|
+
@docstring(TomwerScanBase)
|
503
|
+
def scan_parent_dir_basename(self):
|
504
|
+
if self.master_file is not None:
|
505
|
+
try:
|
506
|
+
return os.path.dirname(os.path.dirname(self.master_file))
|
507
|
+
except Exception:
|
508
|
+
return None
|
509
|
+
else:
|
510
|
+
return None
|
511
|
+
|
512
|
+
def get_proposal_name(self) -> Optional[str]:
|
513
|
+
if self._proposal_name is None and self.master_file is not None:
|
514
|
+
bliss_raw_data_files = self.get_bliss_orginal_files() or ()
|
515
|
+
bliss_raw_data_file = (
|
516
|
+
bliss_raw_data_files[0] if len(bliss_raw_data_files) > 0 else None
|
517
|
+
)
|
518
|
+
if bliss_raw_data_file is not None:
|
519
|
+
strips = bliss_raw_data_file.lstrip("/").split("/")
|
520
|
+
if len(strips) > 2 and bliss_raw_data_file.startswith(
|
521
|
+
("/data/visitor", "/data/visitor")
|
522
|
+
):
|
523
|
+
self._proposal_name = strips[2]
|
524
|
+
elif (
|
525
|
+
bliss_raw_data_file.startswith(("/data", "data"))
|
526
|
+
and len(strips) > 3
|
527
|
+
and strips[2] == "inhouse"
|
528
|
+
):
|
529
|
+
self._proposal_name = strips[3]
|
530
|
+
else:
|
531
|
+
_logger.warning(
|
532
|
+
"this doesn't looks like a bliss file aquired at the ESRF. Unable to find proposal name"
|
533
|
+
)
|
534
|
+
return self._proposal_name
|