tomwer 1.3.0.dev2__py3-none-any.whl → 1.3.0rc10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orangecontrib/tomwer/widgets/__init__.py +11 -12
- orangecontrib/tomwer/widgets/control/DataListenerOW.py +6 -6
- orangecontrib/tomwer/widgets/control/DataValidatorOW.py +6 -6
- orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +3 -3
- orangecontrib/tomwer/widgets/control/NXTomomillOW.py +10 -8
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +6 -6
- orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +1 -1
- orangecontrib/tomwer/widgets/icat/RawDataScreenshotCreatorOW.py +98 -98
- orangecontrib/tomwer/widgets/icat/SaveToGalleryAndPublishOW.py +129 -129
- orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +13 -12
- orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +11 -9
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +11 -9
- orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +12 -15
- orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +9 -9
- orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -1
- tomwer/__main__.py +0 -10
- tomwer/app/canvas_launcher/config.py +3 -3
- tomwer/app/canvas_launcher/environ.py +1 -0
- tomwer/app/intensitynormalization.py +12 -11
- tomwer/app/nabuapp.py +0 -11
- tomwer/app/zstitching.py +11 -1
- tomwer/core/process/control/datalistener/datalistener.py +15 -10
- tomwer/core/process/control/nxtomomill.py +1 -1
- tomwer/core/process/control/scantransfer.py +8 -32
- tomwer/core/process/edit/darkflatpatch.py +8 -9
- tomwer/core/process/edit/imagekeyeditor.py +20 -22
- tomwer/core/process/icat/screenshots.py +1 -0
- tomwer/core/process/reconstruction/axis/axis.py +263 -59
- tomwer/core/process/reconstruction/axis/mode.py +161 -50
- tomwer/core/process/reconstruction/axis/params.py +23 -20
- tomwer/core/process/reconstruction/darkref/darkrefs.py +12 -13
- tomwer/core/process/reconstruction/nabu/castvolume.py +3 -3
- tomwer/core/process/reconstruction/nabu/nabucommon.py +43 -19
- tomwer/core/process/reconstruction/nabu/nabuscores.py +34 -7
- tomwer/core/process/reconstruction/nabu/nabuslices.py +81 -26
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +31 -26
- tomwer/core/process/reconstruction/nabu/plane.py +9 -0
- tomwer/core/process/reconstruction/nabu/utils.py +32 -9
- tomwer/core/process/reconstruction/saaxis/saaxis.py +4 -1
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +9 -1
- tomwer/core/process/reconstruction/scores/params.py +3 -3
- tomwer/core/process/reconstruction/test/test_darkref_copy.py +4 -4
- tomwer/core/process/stitching/nabustitcher.py +11 -10
- tomwer/core/process/task.py +33 -27
- tomwer/core/process/test/test_axis.py +7 -6
- tomwer/core/process/test/test_data_transfer.py +3 -3
- tomwer/core/process/test/test_nabu.py +10 -2
- tomwer/core/process/test/test_normalization.py +2 -2
- tomwer/core/scan/blissscan.py +3 -3
- tomwer/core/scan/edfscan.py +9 -9
- tomwer/core/scan/nxtomoscan.py +11 -11
- tomwer/core/scan/scanbase.py +31 -24
- tomwer/core/scan/test/test_future_scan.py +1 -1
- tomwer/core/scan/test/test_h5.py +4 -4
- tomwer/core/scan/test/test_process_registration.py +2 -2
- tomwer/core/scan/test/test_scan.py +1 -75
- tomwer/core/settings.py +3 -3
- tomwer/core/test/test_utils.py +2 -2
- tomwer/core/volume/edfvolume.py +6 -6
- tomwer/core/volume/hdf5volume.py +6 -6
- tomwer/core/volume/jp2kvolume.py +6 -6
- tomwer/core/volume/rawvolume.py +6 -6
- tomwer/core/volume/tiffvolume.py +12 -12
- tomwer/gui/cluster/slurm.py +14 -9
- tomwer/gui/cluster/supervisor.py +12 -0
- tomwer/gui/cluster/test/test_cluster.py +1 -2
- tomwer/gui/cluster/test/test_supervisor.py +1 -1
- tomwer/gui/control/datalist.py +5 -0
- tomwer/gui/control/datawatcher/controlwidget.py +2 -4
- tomwer/gui/control/reducedarkflatselector.py +8 -8
- tomwer/gui/control/test/test_single_tomo_obj.py +1 -1
- tomwer/gui/edit/dkrfpatch.py +4 -4
- tomwer/gui/edit/nxtomowarmer.py +2 -2
- tomwer/gui/edit/test/test_dkrf_patch.py +6 -6
- tomwer/gui/imagefromfile.py +2 -2
- tomwer/gui/qfolderdialog.py +5 -0
- tomwer/gui/reconstruction/axis/CompareImages.py +94 -168
- tomwer/gui/reconstruction/axis/radioaxis.py +58 -182
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -1
- tomwer/gui/reconstruction/nabu/castvolume.py +8 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +54 -21
- tomwer/gui/reconstruction/normalization/intensity.py +3 -25
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +1 -1
- tomwer/gui/reconstruction/saaxis/saaxis.py +1 -11
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +0 -10
- tomwer/gui/reconstruction/scores/scoreplot.py +1 -6
- tomwer/gui/reconstruction/test/test_axis.py +18 -4
- tomwer/gui/reconstruction/test/test_nabu.py +3 -0
- tomwer/gui/stitching/stitching.py +2 -2
- tomwer/gui/stitching/stitching_preview.py +7 -53
- tomwer/gui/stitching/stitching_raw.py +3 -3
- tomwer/gui/utils/inputwidget.py +12 -2
- tomwer/gui/utils/lineselector/lineselector.py +1 -1
- tomwer/gui/visualization/dataviewer.py +47 -17
- tomwer/gui/visualization/sinogramviewer.py +19 -26
- tomwer/gui/visualization/test/test_volumeviewer.py +64 -66
- tomwer/gui/visualization/volumeviewer.py +105 -105
- tomwer/io/utils/h5pyutils.py +7 -3
- tomwer/io/utils/utils.py +3 -3
- tomwer/resources/gui/icons/parameters.svg +1 -1
- tomwer/resources/gui/illustrations/no_rot.svg +1 -1
- tomwer/synctools/stacks/edit/darkflatpatch.py +17 -12
- tomwer/tests/test_scripts.py +0 -3
- tomwer/third_part/WaitingOverlay.py +110 -0
- tomwer/third_part/__init__.py +0 -0
- tomwer/version.py +2 -2
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/METADATA +32 -31
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/RECORD +115 -153
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/WHEEL +1 -1
- orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +0 -197
- orangecontrib/tomwer/widgets/reconstruction/icons/XY_lamino.svg +0 -168
- orangecontrib/tomwer/widgets/reconstruction/icons/XZ_lamino.svg +0 -275
- orangecontrib/tomwer/widgets/reconstruction/icons/YZ_lamino.svg +0 -182
- tomwer/app/lamino.py +0 -143
- tomwer/core/process/reconstruction/lamino/__init__.py +0 -1
- tomwer/core/process/reconstruction/lamino/tofu.py +0 -1000
- tomwer/core/process/test/test_lamino.py +0 -76
- tomwer/core/test/test_lamino.py +0 -92
- tomwer/gui/reconstruction/lamino/__init__.py +0 -31
- tomwer/gui/reconstruction/lamino/tofu/TofuOptionLoader.py +0 -107
- tomwer/gui/reconstruction/lamino/tofu/__init__.py +0 -1
- tomwer/gui/reconstruction/lamino/tofu/misc.py +0 -148
- tomwer/gui/reconstruction/lamino/tofu/projections.py +0 -896
- tomwer/gui/reconstruction/lamino/tofu/settings.py +0 -75
- tomwer/gui/reconstruction/lamino/tofu/tofu.py +0 -432
- tomwer/gui/reconstruction/lamino/tofu/tofuexpert.py +0 -567
- tomwer/gui/reconstruction/lamino/tofu/tofuoutput.py +0 -757
- tomwer/gui/reconstruction/test/test_lamino.py +0 -194
- tomwer/resources/gui/icons/lamino_parameters.svg +0 -70
- tomwer/resources/gui/illustrations/lamino_angle.png +0 -0
- tomwer/resources/gui/illustrations/lamino_angle.svg +0 -509
- tomwer/resources/gui/illustrations/lamino_beta_angle.png +0 -0
- tomwer/resources/gui/illustrations/lamino_beta_angle.svg +0 -97
- tomwer/resources/gui/illustrations/lamino_theta_angle.png +0 -0
- tomwer/resources/gui/illustrations/lamino_theta_angle.svg +0 -368
- tomwer/resources/gui/illustrations/manual_slice.png +0 -0
- tomwer/resources/gui/illustrations/manual_slice.svg +0 -221
- tomwer/resources/gui/illustrations/psi_angle.png +0 -0
- tomwer/resources/gui/illustrations/psi_angle.svg +0 -479
- tomwer/resources/gui/illustrations/rotation_center.png +0 -0
- tomwer/resources/gui/illustrations/rotation_center.svg +0 -276
- tomwer/resources/gui/illustrations/slice_stack.png +0 -0
- tomwer/resources/gui/illustrations/slice_stack.svg +0 -266
- tomwer/resources/gui/illustrations/xy_slice.png +0 -0
- tomwer/resources/gui/illustrations/xy_slice.svg +0 -269
- tomwer/resources/gui/illustrations/xz_slice.png +0 -0
- tomwer/resources/gui/illustrations/xz_slice.svg +0 -270
- tomwer/resources/gui/illustrations/yz_slice.png +0 -0
- tomwer/resources/gui/illustrations/yz_slice.svg +0 -270
- tomwer/synctools/stacks/reconstruction/lamino.py +0 -233
- /tomwer-1.3.0.dev2-py3.11-nspkg.pth → /tomwer-1.3.0rc10-py3.11-nspkg.pth +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/LICENSE +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/entry_points.txt +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.3.0.dev2.dist-info → tomwer-1.3.0rc10.dist-info}/top_level.txt +0 -0
@@ -41,6 +41,7 @@ from processview.core.manager.manager import ProcessManager, DatasetState
|
|
41
41
|
from tomwer.core.futureobject import FutureTomwerObject
|
42
42
|
from tomwer.core.utils.scanutils import data_identifier_to_scan
|
43
43
|
from tomwer.core.utils.slurm import is_slurm_available
|
44
|
+
from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
|
44
45
|
from tomwer.core.process.reconstruction.nabu.utils import slice_index_to_int
|
45
46
|
from tomwer.core.process.icat.gallery import (
|
46
47
|
IcatScreenshots,
|
@@ -83,7 +84,7 @@ from processview.core.superviseprocess import SuperviseProcess
|
|
83
84
|
from silx.io.dictdump import h5todict
|
84
85
|
from silx.io.utils import h5py_read_dataset
|
85
86
|
from silx.utils.enum import Enum as _Enum
|
86
|
-
from tomoscan.io import HDF5File
|
87
|
+
from tomoscan.io import HDF5File, get_swmr_mode
|
87
88
|
|
88
89
|
from tomwer.core.process.task import Task
|
89
90
|
from tomwer.core.scan.edfscan import EDFTomoScan
|
@@ -201,6 +202,7 @@ def run_slices_reconstruction(
|
|
201
202
|
ask_sinogram_registration=ask_sinogram_registration,
|
202
203
|
ask_sinogram_load=ask_sinogram_load,
|
203
204
|
instanciate_class_only=instanciate_classes_only,
|
205
|
+
axis=config.get("reconstruction", {}).get("slice_plane", "XY"),
|
204
206
|
)
|
205
207
|
|
206
208
|
# specific treatments of results
|
@@ -443,15 +445,14 @@ class NabuSlicesTask(
|
|
443
445
|
)
|
444
446
|
|
445
447
|
# register result
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
)
|
448
|
+
self.register_process(
|
449
|
+
process_file=scan.process_file,
|
450
|
+
entry=entry,
|
451
|
+
configuration=configuration,
|
452
|
+
results={},
|
453
|
+
process_index=process_index,
|
454
|
+
overwrite=True,
|
455
|
+
)
|
455
456
|
if self.get_input_value("serialize_output_data", True):
|
456
457
|
self.outputs.data = scan.to_dict()
|
457
458
|
else:
|
@@ -493,7 +494,7 @@ class NabuSlicesTask(
|
|
493
494
|
:rtype:dict
|
494
495
|
"""
|
495
496
|
if entry is None:
|
496
|
-
with HDF5File(process_file, "r", swmr=
|
497
|
+
with HDF5File(process_file, "r", swmr=get_swmr_mode()) as h5f:
|
497
498
|
entries = NabuSlicesTask._get_process_nodes(
|
498
499
|
root_node=h5f, process=NabuSlicesTask
|
499
500
|
)
|
@@ -509,7 +510,7 @@ class NabuSlicesTask(
|
|
509
510
|
configuration_path = None
|
510
511
|
res = {}
|
511
512
|
|
512
|
-
with HDF5File(process_file, "r", swmr=
|
513
|
+
with HDF5File(process_file, "r", swmr=get_swmr_mode()) as h5f:
|
513
514
|
nabu_nodes = NabuSlicesTask._get_process_nodes(
|
514
515
|
root_node=h5f[entry], process=NabuSlicesTask
|
515
516
|
)
|
@@ -587,7 +588,13 @@ def interpret_tomwer_configuration(
|
|
587
588
|
return nabu_config
|
588
589
|
|
589
590
|
if "tomwer_slices" in config and scan is not None:
|
590
|
-
slices = list(
|
591
|
+
slices = list(
|
592
|
+
NabuSliceMode.getSlices(
|
593
|
+
config["tomwer_slices"],
|
594
|
+
scan=scan,
|
595
|
+
axis=config.get("reconstruction", {}).get("slice_plane", "XY"),
|
596
|
+
)
|
597
|
+
)
|
591
598
|
else:
|
592
599
|
slices = []
|
593
600
|
|
@@ -631,6 +638,7 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
631
638
|
config: dict,
|
632
639
|
dry_run: bool,
|
633
640
|
slice_index: Union[int, str, None],
|
641
|
+
axis: NabuPlane,
|
634
642
|
target: Target,
|
635
643
|
ask_sinogram_registration: bool,
|
636
644
|
ask_sinogram_load: bool,
|
@@ -644,6 +652,7 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
644
652
|
target=target,
|
645
653
|
cluster_config=cluster_config,
|
646
654
|
process_name=process_name,
|
655
|
+
axis=axis,
|
647
656
|
)
|
648
657
|
self._slice_index = slice_index
|
649
658
|
if not isinstance(config, dict):
|
@@ -686,7 +695,9 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
686
695
|
"""
|
687
696
|
if isinstance(self.slice_index, str):
|
688
697
|
self._slice_index = slice_index_to_int(
|
689
|
-
slice_index=self.slice_index,
|
698
|
+
slice_index=self.slice_index,
|
699
|
+
scan=self.scan,
|
700
|
+
axis=self.axis,
|
690
701
|
)
|
691
702
|
elif (
|
692
703
|
isinstance(self.slice_index, float)
|
@@ -734,8 +745,19 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
734
745
|
# the policy is to save nabu .cfg file at the same location as the
|
735
746
|
# force overwrite results
|
736
747
|
if self.slice_index is not None:
|
737
|
-
|
738
|
-
|
748
|
+
if self.axis is NabuPlane.YZ:
|
749
|
+
config["reconstruction"]["start_x"] = self.slice_index
|
750
|
+
config["reconstruction"]["end_x"] = self.slice_index
|
751
|
+
elif self.axis is NabuPlane.XZ:
|
752
|
+
config["reconstruction"]["start_y"] = self.slice_index
|
753
|
+
config["reconstruction"]["end_y"] = self.slice_index
|
754
|
+
elif self.axis is NabuPlane.XY:
|
755
|
+
config["reconstruction"]["start_z"] = self.slice_index
|
756
|
+
config["reconstruction"]["end_z"] = self.slice_index
|
757
|
+
else:
|
758
|
+
raise ValueError(
|
759
|
+
f"self.axis has an invalid value: {self.axis} when expected to be in {NabuPlane.values()}"
|
760
|
+
)
|
739
761
|
|
740
762
|
if self.slice_index is not None:
|
741
763
|
os.makedirs(config["output"]["location"], exist_ok=True)
|
@@ -763,8 +785,6 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
763
785
|
self._process_config(
|
764
786
|
config_to_dump=config_to_dump,
|
765
787
|
config_file=conf_file,
|
766
|
-
start_z=None,
|
767
|
-
end_z=None,
|
768
788
|
info="nabu slice reconstruction",
|
769
789
|
file_format=config_to_dump["output"]["file_format"],
|
770
790
|
process_name=self.process_name,
|
@@ -798,6 +818,7 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
798
818
|
file_format=file_format,
|
799
819
|
scan=self.scan,
|
800
820
|
slice_index=None,
|
821
|
+
axis=self.axis,
|
801
822
|
)
|
802
823
|
|
803
824
|
return (CallBack(callback, self.scan),)
|
@@ -806,19 +827,25 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
806
827
|
|
807
828
|
@staticmethod
|
808
829
|
def get_file_basename_reconstruction(
|
809
|
-
scan,
|
830
|
+
scan,
|
831
|
+
pag,
|
832
|
+
ctf,
|
833
|
+
db,
|
834
|
+
slice_index: Union[str, int],
|
835
|
+
axis: NabuPlane,
|
810
836
|
):
|
837
|
+
axis = NabuPlane.from_value(axis)
|
811
838
|
if pag:
|
812
839
|
assert db is not None, "if paganin defined, db should not be None"
|
813
840
|
if slice_index is not None:
|
814
|
-
slice_index = slice_index_to_int(slice_index, scan=scan)
|
841
|
+
slice_index = slice_index_to_int(slice_index, scan=scan, axis=axis)
|
815
842
|
|
816
843
|
assert type(db) in (int, type(None))
|
817
844
|
if isinstance(scan, NXtomoScan):
|
818
845
|
basename, _ = os.path.splitext(scan.master_file)
|
819
846
|
basename = os.path.basename(basename)
|
820
847
|
try:
|
821
|
-
with HDF5File(scan.master_file, mode="r") as h5f:
|
848
|
+
with HDF5File(scan.master_file, mode="r", swmr=get_swmr_mode()) as h5f:
|
822
849
|
if len(h5f.keys()) > 1:
|
823
850
|
# if there is more than one entry in the file append the entry name to the file basename
|
824
851
|
basename = "_".join((basename, scan.entry.lstrip("/")))
|
@@ -840,6 +867,8 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
840
867
|
basename + "slice_pag",
|
841
868
|
str(slice_index).zfill(6),
|
842
869
|
"db" + str(db).zfill(4),
|
870
|
+
"plane",
|
871
|
+
axis.value,
|
843
872
|
)
|
844
873
|
)
|
845
874
|
elif ctf:
|
@@ -848,13 +877,22 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
848
877
|
basename + "slice_ctf",
|
849
878
|
str(slice_index).zfill(6),
|
850
879
|
"db" + str(db).zfill(4),
|
880
|
+
"plane",
|
881
|
+
axis.value,
|
851
882
|
)
|
852
883
|
)
|
853
884
|
else:
|
854
|
-
return "_".join(
|
885
|
+
return "_".join(
|
886
|
+
(
|
887
|
+
basename + "slice",
|
888
|
+
str(slice_index).zfill(6),
|
889
|
+
"plane",
|
890
|
+
axis.value,
|
891
|
+
)
|
892
|
+
)
|
855
893
|
|
856
894
|
@docstring(_NabuBaseReconstructor)
|
857
|
-
def _get_file_basename_reconstruction(self, pag, db, ctf):
|
895
|
+
def _get_file_basename_reconstruction(self, pag, db, ctf, axis):
|
858
896
|
"""
|
859
897
|
|
860
898
|
:param TomwerScanBase scan: scan reconstructed
|
@@ -866,7 +904,12 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
866
904
|
:return: basename of the file reconstructed (without any extension)
|
867
905
|
"""
|
868
906
|
return self.get_file_basename_reconstruction(
|
869
|
-
scan=self.scan,
|
907
|
+
scan=self.scan,
|
908
|
+
db=db,
|
909
|
+
pag=pag,
|
910
|
+
slice_index=self.slice_index,
|
911
|
+
ctf=ctf,
|
912
|
+
axis=axis,
|
870
913
|
)
|
871
914
|
|
872
915
|
|
@@ -881,6 +924,7 @@ def run_single_slice_reconstruction(
|
|
881
924
|
cluster_config: Optional[dict] = None,
|
882
925
|
add_to_latest_reconstructions=True,
|
883
926
|
instanciate_class_only=False,
|
927
|
+
axis: NabuPlane = NabuPlane.XY,
|
884
928
|
) -> Optional[ResultsRun]:
|
885
929
|
"""
|
886
930
|
# TODO: might need something like a context or an option "keep" slice in memory
|
@@ -904,6 +948,12 @@ def run_single_slice_reconstruction(
|
|
904
948
|
"""
|
905
949
|
# TODO: remove local from the function signature
|
906
950
|
target = Target.SLURM if cluster_config not in ({}, None) else Target.LOCAL
|
951
|
+
axis = NabuPlane.from_value(axis)
|
952
|
+
# FIXEME: nabu fails if outer_circle activated and if the axis != z
|
953
|
+
if axis != NabuPlane.XY and nabu_config.get("reconstruction", {}).get(
|
954
|
+
"clip_outer_circle", False
|
955
|
+
):
|
956
|
+
nabu_config["reconstruction"]["clip_outer_circle"] = False
|
907
957
|
|
908
958
|
if process_id is not None:
|
909
959
|
try:
|
@@ -918,6 +968,7 @@ def run_single_slice_reconstruction(
|
|
918
968
|
config=nabu_config,
|
919
969
|
dry_run=dry_run,
|
920
970
|
slice_index=slice_index,
|
971
|
+
axis=axis,
|
921
972
|
target=target,
|
922
973
|
ask_sinogram_registration=ask_sinogram_registration,
|
923
974
|
ask_sinogram_load=ask_sinogram_load,
|
@@ -943,7 +994,7 @@ class NabuSliceMode(_Enum):
|
|
943
994
|
OTHER = "other"
|
944
995
|
|
945
996
|
@staticmethod
|
946
|
-
def getSlices(slices, scan) -> tuple:
|
997
|
+
def getSlices(slices, scan, axis=NabuPlane.XY) -> tuple:
|
947
998
|
res = []
|
948
999
|
try:
|
949
1000
|
mode = NabuSliceMode.from_value(slices)
|
@@ -954,7 +1005,11 @@ class NabuSliceMode(_Enum):
|
|
954
1005
|
pass
|
955
1006
|
else:
|
956
1007
|
if mode == mode.MIDDLE:
|
957
|
-
|
1008
|
+
axis = NabuPlane.from_value(axis)
|
1009
|
+
if axis is NabuPlane.XY:
|
1010
|
+
n_slice = scan.dim_2 or 2048
|
1011
|
+
elif axis in (NabuPlane.YZ, NabuPlane.XZ):
|
1012
|
+
n_slice = scan.dim_1 or 2048
|
958
1013
|
res.append(n_slice // 2)
|
959
1014
|
else:
|
960
1015
|
raise ValueError(
|
@@ -45,7 +45,7 @@ from processview.core.superviseprocess import SuperviseProcess
|
|
45
45
|
from silx.io.utils import h5py_read_dataset
|
46
46
|
from tomwer.core.utils.deprecation import deprecated_warning
|
47
47
|
|
48
|
-
from tomoscan.io import HDF5File
|
48
|
+
from tomoscan.io import HDF5File, get_swmr_mode
|
49
49
|
|
50
50
|
from tomwer.core.cluster.cluster import SlurmClusterConfiguration
|
51
51
|
from tomwer.core.futureobject import FutureTomwerObject
|
@@ -275,8 +275,6 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
275
275
|
self._process_config(
|
276
276
|
config_to_dump=config_to_dump,
|
277
277
|
config_file=conf_file,
|
278
|
-
start_z=config_to_dump["reconstruction"]["start_z"],
|
279
|
-
end_z=config_to_dump["reconstruction"]["end_z"],
|
280
278
|
info="nabu volume reconstruction",
|
281
279
|
file_format=config_slices["output"]["file_format"],
|
282
280
|
process_name=self.process_name,
|
@@ -326,17 +324,16 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
326
324
|
if "postproc" in config:
|
327
325
|
config["postproc"] = config["postproc"]
|
328
326
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
del config["end_z"]
|
327
|
+
# make sure start_[x] and end_[x] come from config
|
328
|
+
for key in ("start_x", "end_x", "start_y", "end_y", "start_z", "end_z"):
|
329
|
+
if key in config:
|
330
|
+
config["reconstruction"][key] = config[key]
|
331
|
+
del config[key]
|
335
332
|
|
336
333
|
return config, nabu_cfg_folder
|
337
334
|
|
338
335
|
@docstring(_NabuBaseReconstructor)
|
339
|
-
def _get_file_basename_reconstruction(self, pag, db, ctf):
|
336
|
+
def _get_file_basename_reconstruction(self, pag, db, ctf, axis):
|
340
337
|
"""
|
341
338
|
|
342
339
|
:param TomwerScanBase scan: scan reconstructed
|
@@ -345,6 +342,7 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
345
342
|
entire volume
|
346
343
|
:param bool pag: is it a paganin reconstruction
|
347
344
|
:param int db: delta / beta parameter
|
345
|
+
:param axis: axis over which the reconstruction goes. For volume always expected to be z. So ignored in the function
|
348
346
|
:return: basename of the file reconstructed (without any extension)
|
349
347
|
"""
|
350
348
|
assert type(db) in (int, type(None))
|
@@ -354,7 +352,9 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
354
352
|
basename = os.path.basename(basename)
|
355
353
|
try:
|
356
354
|
# if there is more than one entry in the file append the entry name to the file basename
|
357
|
-
with HDF5File(
|
355
|
+
with HDF5File(
|
356
|
+
self.scan.master_file, mode="r", swmr=get_swmr_mode()
|
357
|
+
) as h5f:
|
358
358
|
if len(h5f.keys()) > 1:
|
359
359
|
basename = "_".join((basename, self.scan.entry.strip("/")))
|
360
360
|
except Exception:
|
@@ -531,24 +531,29 @@ class NabuVolumeTask(
|
|
531
531
|
self.outputs.future_tomo_obj = future_tomo_obj
|
532
532
|
|
533
533
|
# build screenshots
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
534
|
+
if scan.latest_vol_reconstructions is not None:
|
535
|
+
try:
|
536
|
+
screenshots = {}
|
537
|
+
[
|
538
|
+
screenshots.update(
|
539
|
+
select_screenshot_from_volume(
|
540
|
+
VolumeFactory.create_tomo_object_from_identifier(
|
541
|
+
rec_identifier
|
542
|
+
)
|
543
|
+
)
|
540
544
|
)
|
545
|
+
for rec_identifier in scan.latest_vol_reconstructions
|
546
|
+
]
|
547
|
+
except Exception as e:
|
548
|
+
_logger.error(f"screenshot creation failed. Error is {e}")
|
549
|
+
else:
|
550
|
+
self.outputs.screenshots = IcatScreenshots(
|
551
|
+
data_dir=deduce_dataset_gallery_location(scan),
|
552
|
+
screenshots=screenshots,
|
553
|
+
scan=scan,
|
541
554
|
)
|
542
|
-
for rec_identifier in scan.latest_vol_reconstructions
|
543
|
-
]
|
544
|
-
except Exception as e:
|
545
|
-
_logger.error(f"screenshot creation failed. Error is {e}")
|
546
555
|
else:
|
547
|
-
self.outputs.screenshots =
|
548
|
-
data_dir=deduce_dataset_gallery_location(scan),
|
549
|
-
screenshots=screenshots,
|
550
|
-
scan=scan,
|
551
|
-
)
|
556
|
+
self.outputs.screenshots = tuple()
|
552
557
|
|
553
558
|
def set_configuration(self, configuration: dict) -> None:
|
554
559
|
Task.set_configuration(self, configuration=configuration)
|
@@ -41,6 +41,7 @@ from nabu.pipeline.fullfield.nabu_config import (
|
|
41
41
|
from silx.utils.enum import Enum as _Enum
|
42
42
|
|
43
43
|
import tomwer.version
|
44
|
+
from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
|
44
45
|
from tomwer.core.scan.edfscan import EDFTomoScan
|
45
46
|
from tomwer.core.scan.nxtomoscan import NXtomoScan
|
46
47
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
@@ -148,15 +149,19 @@ def get_recons_volume_identifier(
|
|
148
149
|
file_format: str,
|
149
150
|
scan: TomwerScanBase,
|
150
151
|
slice_index: typing.Union[int, None],
|
152
|
+
axis: NabuPlane,
|
151
153
|
) -> tuple:
|
152
154
|
"""
|
153
155
|
return tuple of DataUrl for existings slices
|
154
156
|
"""
|
157
|
+
axis = NabuPlane.from_value(axis)
|
155
158
|
file_format = file_format.lower()
|
156
159
|
if file_format in ("hdf5", "h5", "hdf"):
|
157
160
|
if slice_index is not None:
|
158
161
|
# case of a single hdf5 file
|
159
|
-
file_name = "_".join(
|
162
|
+
file_name = "_".join(
|
163
|
+
(file_prefix, "plane", axis.value, str(slice_index).zfill(6))
|
164
|
+
)
|
160
165
|
else:
|
161
166
|
file_name = file_prefix
|
162
167
|
file_name = ".".join((file_name, file_format))
|
@@ -176,7 +181,9 @@ def get_recons_volume_identifier(
|
|
176
181
|
elif file_format in ("vol", "raw"):
|
177
182
|
if slice_index is not None:
|
178
183
|
# case of a single hdf5 file
|
179
|
-
file_name = "_".join(
|
184
|
+
file_name = "_".join(
|
185
|
+
(file_prefix, "plane", axis.value, str(slice_index).zfill(6))
|
186
|
+
)
|
180
187
|
else:
|
181
188
|
file_name = file_prefix
|
182
189
|
file_name = ".".join((file_name, file_format))
|
@@ -227,6 +234,7 @@ def get_multi_cor_recons_volume_identifiers(
|
|
227
234
|
file_prefix: str,
|
228
235
|
cors: tuple,
|
229
236
|
file_format: str,
|
237
|
+
axis=NabuPlane.XY,
|
230
238
|
) -> dict:
|
231
239
|
"""
|
232
240
|
util to retrieve Volumes (identifier) reconstructed by nabu-multicor
|
@@ -241,7 +249,11 @@ def get_multi_cor_recons_volume_identifiers(
|
|
241
249
|
"""
|
242
250
|
_logger.info("Deduce volume identifiers for nabu-multicor")
|
243
251
|
if isinstance(slice_index, str):
|
244
|
-
slice_index = slice_index_to_int(
|
252
|
+
slice_index = slice_index_to_int(
|
253
|
+
slice_index=slice_index,
|
254
|
+
scan=scan,
|
255
|
+
axis=axis, # for now we always expect the multicor to be done along Z
|
256
|
+
)
|
245
257
|
assert isinstance(
|
246
258
|
slice_index, int
|
247
259
|
), "slice_index is expected to be an int or to be converted to it"
|
@@ -260,7 +272,6 @@ def get_multi_cor_recons_volume_identifiers(
|
|
260
272
|
if file_format in ("hdf5", "h5", "hdf"):
|
261
273
|
file_path = os.path.join(
|
262
274
|
location,
|
263
|
-
f"{file_prefix}_{cor:.3f}", # this level is expected to be removed on the future nabu versions
|
264
275
|
f"{file_prefix}_{cor:.3f}_{str(slice_index).zfill(5)}.{file_format}",
|
265
276
|
)
|
266
277
|
volume = HDF5Volume(
|
@@ -493,11 +504,14 @@ def update_cfg_file_after_transfer(config_file_path, old_path, new_path):
|
|
493
504
|
|
494
505
|
|
495
506
|
def slice_index_to_int(
|
496
|
-
slice_index: typing.Union[int, str],
|
507
|
+
slice_index: typing.Union[int, str],
|
508
|
+
scan: TomwerScanBase,
|
509
|
+
axis=NabuPlane.XY,
|
497
510
|
) -> int:
|
498
511
|
"""
|
499
512
|
cast a slice to an index. The slice can be a string in ['first', 'last', 'middle']
|
500
513
|
"""
|
514
|
+
axis = NabuPlane.from_value(axis)
|
501
515
|
if slice_index == "fisrt":
|
502
516
|
return 0
|
503
517
|
elif slice_index == "last":
|
@@ -518,11 +532,20 @@ def slice_index_to_int(
|
|
518
532
|
_logger.warning("Scan not provided. Consider the 1024 width detector")
|
519
533
|
# default middle.
|
520
534
|
return 1024
|
521
|
-
elif
|
522
|
-
|
523
|
-
|
535
|
+
elif axis is NabuPlane.XY:
|
536
|
+
if scan.dim_2 is None:
|
537
|
+
_logger.warning("unable to get dim size, guess this is 2048 height")
|
538
|
+
return 1024
|
539
|
+
else:
|
540
|
+
return scan.dim_2 // 2
|
541
|
+
elif axis in (NabuPlane.YZ, NabuPlane.XZ):
|
542
|
+
if scan.dim_1 is None:
|
543
|
+
_logger.warning("unable to get dim size, guess this is 2048 width")
|
544
|
+
return 1024
|
545
|
+
else:
|
546
|
+
return scan.dim_1 // 2
|
524
547
|
else:
|
525
|
-
|
548
|
+
raise ValueError(f"axis {axis} is not handled")
|
526
549
|
else:
|
527
550
|
return int(slice_index)
|
528
551
|
|
@@ -520,7 +520,10 @@ class SAAxisTask(
|
|
520
520
|
cors_res, rois = self._post_processing(
|
521
521
|
scan=scan,
|
522
522
|
slice_index=slice_index,
|
523
|
-
cor_reconstructions=
|
523
|
+
cor_reconstructions={
|
524
|
+
cor: recons
|
525
|
+
for cor, recons in zip(params.cors, cor_reconstructions)
|
526
|
+
},
|
524
527
|
)
|
525
528
|
except Exception as e:
|
526
529
|
_logger.error(e)
|
@@ -87,7 +87,7 @@ from .params import SADeltaBetaParams
|
|
87
87
|
_logger = logging.getLogger(__name__)
|
88
88
|
|
89
89
|
|
90
|
-
DEFAULT_RECONS_FOLDER = "
|
90
|
+
DEFAULT_RECONS_FOLDER = "multi_delta_beta_results"
|
91
91
|
|
92
92
|
|
93
93
|
def one_slice_several_db(
|
@@ -250,6 +250,7 @@ class SADeltaBetaTask(
|
|
250
250
|
raise ValueError(f"input type of {scan}: {type(scan)} is not managed")
|
251
251
|
|
252
252
|
config = copy(self.inputs.sa_delta_beta_params)
|
253
|
+
axis = config.get("reconstruction", {}).get("slice_plane", "XY")
|
253
254
|
params = SADeltaBetaParams.from_dict(config)
|
254
255
|
|
255
256
|
# insure scan contains some parameter regarding sa delta / beta
|
@@ -303,6 +304,7 @@ class SADeltaBetaTask(
|
|
303
304
|
slice_index=slice_index,
|
304
305
|
dry_run=dry_run,
|
305
306
|
cluster_config=cluster_config,
|
307
|
+
axis=axis,
|
306
308
|
)
|
307
309
|
except Exception as e:
|
308
310
|
_logger.error(e)
|
@@ -318,6 +320,7 @@ class SADeltaBetaTask(
|
|
318
320
|
slice_index=slice_index,
|
319
321
|
db_reconstructions=dbs_res,
|
320
322
|
future_tomo_objs=future_tomo_objs,
|
323
|
+
axis=axis,
|
321
324
|
)
|
322
325
|
|
323
326
|
# step 4: run post processing (compute score for each slice)
|
@@ -424,6 +427,7 @@ class SADeltaBetaTask(
|
|
424
427
|
slice_index,
|
425
428
|
advancement,
|
426
429
|
dry_run,
|
430
|
+
axis,
|
427
431
|
cluster_config: Optional[dict],
|
428
432
|
):
|
429
433
|
future_tomo_objs = {}
|
@@ -448,6 +452,7 @@ class SADeltaBetaTask(
|
|
448
452
|
process_id=self.process_id,
|
449
453
|
instanciate_classes_only=True,
|
450
454
|
output_file_prefix_pattern=None,
|
455
|
+
axis=axis,
|
451
456
|
)
|
452
457
|
|
453
458
|
for runner in runners:
|
@@ -510,6 +515,7 @@ class SADeltaBetaTask(
|
|
510
515
|
nabu_config: dict,
|
511
516
|
db_reconstructions,
|
512
517
|
slice_index,
|
518
|
+
axis,
|
513
519
|
future_tomo_objs: dict,
|
514
520
|
):
|
515
521
|
assert isinstance(nabu_config, dict)
|
@@ -536,6 +542,7 @@ class SADeltaBetaTask(
|
|
536
542
|
pag=pag,
|
537
543
|
db=int(db) if db is not None else None,
|
538
544
|
ctf=ctf,
|
545
|
+
axis=axis,
|
539
546
|
)
|
540
547
|
# retrieve url
|
541
548
|
volume_identifier = nabu_utils.get_recons_volume_identifier(
|
@@ -544,6 +551,7 @@ class SADeltaBetaTask(
|
|
544
551
|
file_format=nabu_config.get("file_format", "hdf5"),
|
545
552
|
scan=scan,
|
546
553
|
slice_index=None,
|
554
|
+
axis=axis,
|
547
555
|
)
|
548
556
|
|
549
557
|
assert len(volume_identifier) <= 1, "only one slice expected"
|
@@ -179,9 +179,9 @@ class SABaseParams:
|
|
179
179
|
"dry_run": self.dry_run,
|
180
180
|
"output_dir": self.output_dir or "",
|
181
181
|
"score_method": self.score_method.value,
|
182
|
-
"cluster_config":
|
183
|
-
|
184
|
-
|
182
|
+
"cluster_config": (
|
183
|
+
self.cluster_config if self.cluster_config is not None else ""
|
184
|
+
),
|
185
185
|
}
|
186
186
|
|
187
187
|
def load_from_dict(self, dict_: dict):
|
@@ -35,8 +35,8 @@ def test_register_and_copy_darks_and_flats(
|
|
35
35
|
scan_with_raw = MockNXtomo(
|
36
36
|
scan_path=scan_folder_with_raw,
|
37
37
|
create_ini_dark=True,
|
38
|
-
|
39
|
-
|
38
|
+
create_ini_flat=True,
|
39
|
+
create_final_flat=False,
|
40
40
|
n_proj=10,
|
41
41
|
n_ini_proj=10,
|
42
42
|
dim=12,
|
@@ -44,8 +44,8 @@ def test_register_and_copy_darks_and_flats(
|
|
44
44
|
scan_without_raw = MockNXtomo(
|
45
45
|
scan_path=scan_folder_without_raw,
|
46
46
|
create_ini_dark=False,
|
47
|
-
|
48
|
-
|
47
|
+
create_ini_flat=False,
|
48
|
+
create_final_flat=False,
|
49
49
|
n_proj=10,
|
50
50
|
n_ini_proj=10,
|
51
51
|
dim=12,
|
@@ -139,32 +139,33 @@ class StitchingPostProcAggregation(_StitchingPostProcAggregation):
|
|
139
139
|
once stitching is done remotly we need to 'aggregate' the different part in the correct order
|
140
140
|
"""
|
141
141
|
|
142
|
-
def __init__(self,
|
142
|
+
def __init__(self, *args, **kwargs) -> None:
|
143
|
+
super().__init__(*args, **kwargs)
|
143
144
|
self._n_finished = 0
|
144
|
-
|
145
|
-
if isinstance(stitching_config, dict):
|
145
|
+
|
146
|
+
if isinstance(self.stitching_config, dict):
|
146
147
|
stitching_type = StitchingType.from_value(
|
147
|
-
stitching_config["stitching"]["type"]
|
148
|
+
self.stitching_config["stitching"]["type"]
|
148
149
|
)
|
149
150
|
if stitching_type is StitchingType.Z_PREPROC:
|
150
151
|
self._stitching_config = PreProcessedZStitchingConfiguration.from_dict(
|
151
|
-
stitching_config
|
152
|
+
self.stitching_config
|
152
153
|
)
|
153
154
|
elif stitching_type is StitchingType.Z_POSTPROC:
|
154
155
|
self._stitching_config = PostProcessedZStitchingConfiguration.from_dict(
|
155
|
-
stitching_config
|
156
|
+
self.stitching_config
|
156
157
|
)
|
157
158
|
else:
|
158
159
|
raise NotImplementedError("stitching type not handled")
|
159
|
-
elif not isinstance(stitching_config, StitchingConfiguration):
|
160
|
+
elif not isinstance(self.stitching_config, StitchingConfiguration):
|
160
161
|
raise TypeError(
|
161
|
-
f"stitching_config is expected to be an instance of {StitchingConfiguration}. {type(stitching_config)} provided instead"
|
162
|
+
f"stitching_config is expected to be an instance of {StitchingConfiguration}. {type(self.stitching_config)} provided instead"
|
162
163
|
)
|
163
|
-
else:
|
164
|
-
self._stitching_config = stitching_config
|
165
164
|
|
166
165
|
def onePartFinished(self, *args, **kwargs):
|
167
166
|
self._n_finished += 1
|
167
|
+
# note: for now we only consider the user of the futures.
|
168
|
+
# if users want to only run post-processing agregation then they will use the nabu CLI for it.
|
168
169
|
if self._n_finished == len(self._futures):
|
169
170
|
_logger.info("All slurm job finished. Will aggregate results")
|
170
171
|
self.process()
|