tomwer 1.4.0rc5__py3-none-any.whl → 1.4.1__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.
Files changed (58) hide show
  1. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +2 -2
  2. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +19 -47
  3. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +8 -3
  4. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +4 -6
  5. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +8 -4
  6. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +0 -4
  7. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +1 -13
  8. tomwer/app/axis.py +0 -1
  9. tomwer/app/intensitynormalization.py +0 -14
  10. tomwer/app/multicor.py +1 -33
  11. tomwer/app/multipag.py +1 -31
  12. tomwer/app/nabuapp.py +0 -1
  13. tomwer/app/patchrawdarkflat.py +0 -3
  14. tomwer/app/reducedarkflat.py +0 -1
  15. tomwer/core/process/control/datalistener/datalistener.py +0 -232
  16. tomwer/core/process/control/datawatcher/datawatcher.py +0 -5
  17. tomwer/core/process/control/scantransfer.py +3 -60
  18. tomwer/core/process/edit/darkflatpatch.py +0 -8
  19. tomwer/core/process/edit/imagekeyeditor.py +2 -19
  20. tomwer/core/process/reconstruction/axis/axis.py +0 -13
  21. tomwer/core/process/reconstruction/darkref/darkrefs.py +0 -59
  22. tomwer/core/process/reconstruction/nabu/nabuslices.py +0 -88
  23. tomwer/core/process/reconstruction/nabu/nabuvolume.py +0 -10
  24. tomwer/core/process/reconstruction/params_cache.py +36 -0
  25. tomwer/core/process/reconstruction/saaxis/saaxis.py +80 -88
  26. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +78 -86
  27. tomwer/core/process/reconstruction/tests/test_params_cache.py +37 -0
  28. tomwer/core/process/script/python.py +0 -19
  29. tomwer/core/process/task.py +0 -290
  30. tomwer/core/process/tests/test_dark_and_flat.py +0 -6
  31. tomwer/core/process/tests/test_data_transfer.py +0 -1
  32. tomwer/core/process/tests/test_data_watcher.py +6 -23
  33. tomwer/core/scan/edfscan.py +0 -11
  34. tomwer/core/scan/nxtomoscan.py +0 -12
  35. tomwer/core/scan/scanbase.py +0 -81
  36. tomwer/gui/reconstruction/axis/CalculationWidget.py +3 -5
  37. tomwer/gui/reconstruction/tests/test_saaxis.py +2 -2
  38. tomwer/gui/reconstruction/tests/test_sadeltabeta.py +2 -2
  39. tomwer/gui/stitching/config/axisparams.py +2 -0
  40. tomwer/synctools/stacks/reconstruction/axis.py +0 -18
  41. tomwer/synctools/tests/test_foldertransfer.py +2 -19
  42. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_i_norm.py +0 -10
  43. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_sa_delta_beta.py +103 -153
  44. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_saaxis.py +117 -152
  45. tomwer/tests/orangecontrib/tomwer/widgets/{tests/test_darkref.py → test_darkref.py} +0 -9
  46. tomwer/tests/orangecontrib/tomwer/widgets/{tests/test_foldertransfert.py → test_foldertransfert.py} +1 -1
  47. tomwer/tests/test_ewoks/test_workflows.py +0 -4
  48. tomwer/version.py +3 -3
  49. {tomwer-1.4.0rc5.dist-info → tomwer-1.4.1.dist-info}/METADATA +2 -3
  50. {tomwer-1.4.0rc5.dist-info → tomwer-1.4.1.dist-info}/RECORD +55 -56
  51. tomwer/core/scan/tests/test_process_registration.py +0 -64
  52. tomwer/core/utils/Singleton.py +0 -36
  53. tomwer/core/utils/locker.py +0 -58
  54. /tomwer/tests/orangecontrib/tomwer/widgets/{tests/test_conditions.py → test_conditions.py} +0 -0
  55. {tomwer-1.4.0rc5.dist-info → tomwer-1.4.1.dist-info}/LICENSE +0 -0
  56. {tomwer-1.4.0rc5.dist-info → tomwer-1.4.1.dist-info}/WHEEL +0 -0
  57. {tomwer-1.4.0rc5.dist-info → tomwer-1.4.1.dist-info}/entry_points.txt +0 -0
  58. {tomwer-1.4.0rc5.dist-info → tomwer-1.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+
3
+ from tomwer.core.scan.scanbase import TomwerScanBase
4
+ from collections import OrderedDict
5
+
6
+ _CACHE: {str, tuple[float | None, dict | None]} = OrderedDict()
7
+ """
8
+ In the case we want to reprocess a scan we (might) need to know the cor and the nabu reconstruction parameters (for nabu slice and volume reconstructions)
9
+ But we are not keeping all those object during the full 'orange canvas' lifecycle, it would be too heavy.
10
+ As a consequence we cache those (small) values (and only those) of the last n scans (n==30) in case users want to reprocess some of those.
11
+ n value is an arbitrary value.
12
+ """
13
+ _CACHE_SIZE = 30
14
+
15
+
16
+ def save_reconstruction_parameters_to_cache(scan: TomwerScanBase):
17
+ # pop if exists. Will move this item as 'last-in'
18
+ _CACHE.pop(scan.get_identifier().to_str(), None)
19
+ _CACHE[scan.get_identifier().to_str()] = (
20
+ None if scan.axis_params is None else scan.axis_params.relative_cor_value,
21
+ None if scan.nabu_recons_params is None else scan.nabu_recons_params,
22
+ )
23
+ if len(_CACHE) > _CACHE_SIZE:
24
+ _CACHE.popitem(last=False)
25
+
26
+
27
+ def load_reconstruction_parameters_from_cache(scan: TomwerScanBase):
28
+ cor, nabu_recons_params = _CACHE.get(scan.get_identifier().to_str(), (None, None))
29
+ if cor is not None and scan.axis_params is not None:
30
+ scan.axis_params.set_relative_value(cor)
31
+ if nabu_recons_params is not None:
32
+ scan.nabu_recons_params = nabu_recons_params
33
+
34
+
35
+ def clear_reconstruction_parameters_cache():
36
+ _CACHE.clear()
@@ -5,15 +5,16 @@ from __future__ import annotations
5
5
 
6
6
  import logging
7
7
  import os
8
-
9
8
  import h5py
9
+
10
10
  import numpy
11
11
  from multiprocessing import Pool
12
12
  from processview.core.manager import DatasetState, ProcessManager
13
13
  from processview.core.superviseprocess import SuperviseProcess
14
14
  from silx.io.url import DataUrl
15
- from tomwer.core.utils.deprecation import deprecated_warning
15
+ from silx.io.utils import h5py_read_dataset
16
16
 
17
+ from tomwer.core.utils.deprecation import deprecated_warning
17
18
  from tomoscan.io import HDF5File
18
19
 
19
20
  import tomwer.version
@@ -33,13 +34,14 @@ from tomwer.core.process.reconstruction.scores import (
33
34
  from tomwer.core.process.reconstruction.scores.params import ScoreMethod
34
35
  from tomwer.core.process.reconstruction.utils.cor import relative_pos_to_absolute
35
36
  from tomwer.core.process.task import Task
36
- from tomwer.core.scan.nxtomoscan import NXtomoScan
37
+ from tomwer.core.process import utils as core_utils
37
38
  from tomwer.core.scan.scanbase import TomwerScanBase
38
39
  from tomwer.core.scan.scanfactory import ScanFactory
39
40
  from tomwer.core.utils import logconfig
40
- from tomwer.core.utils.locker import FileLockerManager
41
41
  from tomwer.core.utils.scanutils import data_identifier_to_scan
42
42
  from tomwer.core.utils.slurm import is_slurm_available
43
+
44
+ from tomwer.io.utils.h5pyutils import EntryReader
43
45
  from tomwer.core.volume.volumefactory import VolumeFactory
44
46
  from tomwer.io.utils.utils import get_slice_data
45
47
  from tomwer.io.utils import format_stderr_stdout
@@ -378,7 +380,8 @@ class SAAxisTask(
378
380
  output_dir = params.output_dir or None
379
381
  if output_dir is None:
380
382
  output_dir = (
381
- params.nabu_params.get("output", {}).get("location", None) or None
383
+ params.nabu_recons_params.get("output", {}).get("location", None)
384
+ or None
382
385
  )
383
386
  if output_dir is None:
384
387
  output_dir = os.path.join(scan.path, DEFAULT_RECONS_FOLDER)
@@ -576,35 +579,23 @@ class SAAxisTask(
576
579
  _logger.error(e)
577
580
  else:
578
581
  if self._dump_process:
579
- process_idx = SAAxisTask.process_to_tomwer_processes(
580
- scan=scan,
581
- )
582
- if self.dump_roi and process_idx is not None:
583
- self.dump_rois(
584
- scan, score_rois=score_rois, process_index=process_idx
585
- )
582
+ self.save_results_to_disk(scan=scan)
583
+ if self.dump_roi:
584
+ self.dump_rois(scan, score_rois=score_rois)
586
585
 
587
586
  @staticmethod
588
- def dump_rois(scan, score_rois, process_index):
589
- process_file = scan.process_file
590
- process_name = "tomwer_process_" + str(process_index)
591
-
587
+ def dump_rois(scan, score_rois):
592
588
  if scan.saaxis_params.scores in (None, {}):
593
589
  return
594
590
 
595
- def get_process_path():
596
- return "/".join((scan.entry or "entry", process_name))
591
+ process_url = SAAxisTask.get_results_url(scan=scan)
597
592
 
598
- # save it to the file
599
- with FileLockerManager.get_lock(process_file):
600
- # needs an extra lock for multiprocessing
601
-
602
- with HDF5File(process_file, mode="a") as h5f:
603
- nx_process = h5f.require_group(get_process_path())
604
- score_roi_grp = nx_process.require_group("score_roi")
605
- for cor, roi in score_rois.items():
606
- score_roi_grp[str(cor)] = roi
607
- score_roi_grp[str(cor)].attrs["interpretation"] = "image"
593
+ with HDF5File(process_url.file_path(), mode="w") as h5f:
594
+ nx_process = h5f.require_group(process_url.data_path())
595
+ score_roi_grp = nx_process.require_group("score_roi")
596
+ for cor, roi in score_rois.items():
597
+ score_roi_grp[str(cor)] = roi
598
+ score_roi_grp[str(cor)].attrs["interpretation"] = "image"
608
599
 
609
600
  @staticmethod
610
601
  def program_name():
@@ -622,74 +613,75 @@ class SAAxisTask(
622
613
  return "Semi automatic center of rotation / axis calculation"
623
614
 
624
615
  @staticmethod
625
- def process_to_tomwer_processes(scan):
626
- if scan.process_file is not None:
627
- entry = "entry"
628
- if isinstance(scan, NXtomoScan):
629
- entry = scan.entry
630
-
631
- cor = None
632
- if hasattr(scan, "axis_params"):
633
- cor = scan.axis_params.relative_cor_value
634
-
635
- process_index = scan.pop_process_index()
636
- try:
637
- with scan.acquire_process_file_lock():
638
- Task._register_process(
639
- process_file=scan.process_file,
640
- entry=entry,
641
- results={"center_of_rotation": cor if cor is not None else "-"},
642
- configuration=scan.saaxis_params.to_dict(),
643
- process_index=process_index,
644
- overwrite=True,
645
- process=SAAxisTask,
646
- )
647
- SAAxisTask._extends_results(
648
- scan=scan, entry=entry, process_index=process_index
649
- )
650
- except Exception as e:
651
- _logger.warning(
652
- f"Fail to register process of with index {process_index}. Reason is {e}"
653
- )
654
- return process_index
616
+ def get_results_url(scan):
617
+ return DataUrl(
618
+ file_path=scan.get_relative_file(
619
+ os.path.join(DEFAULT_RECONS_FOLDER, "tomwer_saaxis.h5")
620
+ ),
621
+ data_path=scan.entry or "entry",
622
+ scheme="silx",
623
+ )
655
624
 
656
625
  @staticmethod
657
- def _extends_results(scan, entry, process_index):
658
- process_file = scan.process_file
659
- process_name = "tomwer_process_" + str(process_index)
660
-
626
+ def save_results_to_disk(scan):
661
627
  if scan.saaxis_params.scores in (None, {}):
662
628
  return
663
629
 
664
- def get_process_path():
665
- return "/".join((entry or "entry", process_name))
630
+ saaxis_results_url = SAAxisTask.get_results_url(scan=scan)
666
631
 
667
632
  # save it to the file
668
- with FileLockerManager().get_lock(process_file):
669
- # needs an extra lock for multiprocessing
670
-
671
- with HDF5File(process_file, mode="a") as h5f:
672
- nx_process = h5f.require_group(get_process_path())
673
- if "NX_class" not in nx_process.attrs:
674
- nx_process.attrs["NX_class"] = "NXprocess"
675
-
676
- results = nx_process.require_group("results")
677
- for cor, (url, score) in scan.saaxis_params.scores.items():
678
- results_cor = results.require_group(str(cor))
679
- for method in ScoreMethod:
680
- method_score = score.get(method)
681
- if method_score is None:
682
- results_cor[method.value] = "None"
683
- else:
684
- results_cor[method.value] = method_score
685
-
686
- link_path = os.path.relpath(
687
- url.file_path(),
688
- os.path.dirname(process_file),
689
- )
690
- results_cor["reconstructed_slice"] = h5py.ExternalLink(
691
- link_path, url.data_path()
633
+ with HDF5File(saaxis_results_url.file_path(), mode="a") as h5f:
634
+ nx_process = h5f.require_group(saaxis_results_url.data_path())
635
+ if "NX_class" not in nx_process.attrs:
636
+ nx_process.attrs["NX_class"] = "NXprocess"
637
+
638
+ results = nx_process.require_group("results")
639
+ for cor, (url, score) in scan.saaxis_params.scores.items():
640
+ results_cor = results.require_group(str(cor))
641
+ for method in ScoreMethod:
642
+ method_score = score.get(method)
643
+ if method_score is None:
644
+ results_cor[method.value] = "None"
645
+ else:
646
+ results_cor[method.value] = method_score
647
+
648
+ link_path = os.path.relpath(
649
+ url.file_path(),
650
+ os.path.dirname(saaxis_results_url.file_path()),
651
+ )
652
+ results_cor["reconstructed_slice"] = h5py.ExternalLink(
653
+ link_path, url.data_path()
654
+ )
655
+
656
+ @staticmethod
657
+ def load_results_from_disk(scan):
658
+ saaxis_results_url = SAAxisTask.get_results_url(scan=scan)
659
+
660
+ if saaxis_results_url.file_path() is None or not os.path.exists(
661
+ saaxis_results_url.file_path()
662
+ ):
663
+ _logger.warning(
664
+ "Unable to find process file. Unable to read " "existing processing"
665
+ )
666
+ return None, None
667
+
668
+ try:
669
+ with EntryReader(saaxis_results_url) as h5f_entry_node:
670
+ scores = core_utils.get_scores(h5f_entry_node)
671
+ if (
672
+ "results" in h5f_entry_node
673
+ and "center_of_rotation" in h5f_entry_node["results"]
674
+ ):
675
+ selected = h5py_read_dataset(
676
+ h5f_entry_node["results"]["center_of_rotation"]
692
677
  )
678
+ else:
679
+ _logger.warning(f"no results found for {scan}")
680
+ selected = None
681
+ return scores, selected
682
+ except ValueError:
683
+ _logger.warning(f"Data path ({saaxis_results_url.data_path()}) not found")
684
+ return None, None
693
685
 
694
686
  def cancel(self):
695
687
  """
@@ -20,6 +20,7 @@ from processview.core.manager import DatasetState, ProcessManager
20
20
  from processview.core.superviseprocess import SuperviseProcess
21
21
  from tomoscan.esrf.scan.utils import get_data
22
22
  from tomoscan.io import HDF5File
23
+ from silx.io.utils import h5py_read_dataset
23
24
 
24
25
  import tomwer.version
25
26
  from tomwer.core.process.reconstruction.nabu.nabucommon import (
@@ -36,21 +37,21 @@ from tomwer.core.process.reconstruction.scores import (
36
37
  compute_score,
37
38
  get_disk_mask_radius,
38
39
  )
39
- from tomwer.core.utils.locker import FileLockerManager
40
40
  from tomwer.core.process.task import Task
41
- from tomwer.core.scan.nxtomoscan import NXtomoScan
41
+ from tomwer.core.process import utils as core_utils
42
42
  from tomwer.core.scan.scanbase import TomwerScanBase
43
43
  from tomwer.core.scan.scanfactory import ScanFactory
44
44
  from tomwer.core.utils import logconfig
45
45
  from tomwer.core.utils.scanutils import data_identifier_to_scan
46
46
  from tomwer.core.volume.volumefactory import VolumeFactory
47
47
  from tomwer.io.utils import format_stderr_stdout
48
+ from tomwer.io.utils.h5pyutils import EntryReader
48
49
  from tomwer.core.process.reconstruction.nabu.nabuscores import (
49
50
  run_nabu_one_slice_several_config,
50
51
  )
51
52
  from tomwer.core.futureobject import FutureTomwerObject
52
53
 
53
-
54
+ from silx.io.url import DataUrl
54
55
  from silx.utils.deprecation import deprecated, deprecated_warning
55
56
 
56
57
  from ..nabu import utils as nabu_utils
@@ -202,7 +203,8 @@ class SADeltaBetaTask(
202
203
 
203
204
  if params.output_dir is None:
204
205
  output_dir = (
205
- params.nabu_params.get("output", {}).get("location", None) or None
206
+ params.nabu_recons_params.get("output", {}).get("location", None)
207
+ or None
206
208
  )
207
209
  if output_dir is None:
208
210
  output_dir = os.path.join(scan.path, DEFAULT_RECONS_FOLDER)
@@ -587,39 +589,30 @@ class SADeltaBetaTask(
587
589
  _logger.error(e)
588
590
  else:
589
591
  if self._dump_process:
590
- process_idx = SADeltaBetaTask.process_to_tomwer_processes(
591
- scan=scan,
592
- )
593
- if self.dump_roi and process_idx is not None:
594
- self.dump_rois(
595
- scan, score_rois=score_rois, process_index=process_idx
596
- )
592
+ self.save_results_to_disk(scan=scan)
593
+ if self.dump_roi:
594
+ self.dump_rois(scan, score_rois=score_rois)
597
595
 
598
596
  @staticmethod
599
- def dump_rois(scan, score_rois: dict, process_index: int):
600
- if score_rois is None or len(score_rois) == 0:
601
- return
597
+ def dump_rois(scan, score_rois: dict):
602
598
  if not isinstance(score_rois, dict):
603
599
  raise TypeError("score_rois is expected to be a dict")
604
- process_file = scan.process_file
605
- process_name = f"tomwer_process_{process_index}"
600
+
601
+ if score_rois is None or len(score_rois) == 0:
602
+ return
606
603
 
607
604
  if scan.saaxis_params.scores in (None, {}):
608
605
  return
609
606
 
610
- def get_process_path():
611
- return "/".join((scan.entry or "entry", process_name))
607
+ sa_delta_beta_results_url = SADeltaBetaTask.get_results_url(scan=scan)
612
608
 
613
609
  # save it to the file
614
- with FileLockerManager().get_lock(process_file):
615
- # needs an extra lock for multiprocessing
616
-
617
- with HDF5File(process_file, mode="a") as h5f:
618
- nx_process = h5f.require_group(get_process_path())
619
- score_roi_grp = nx_process.require_group("score_roi")
620
- for db, roi in score_rois.items():
621
- score_roi_grp[str(db)] = roi
622
- score_roi_grp[str(db)].attrs["interpretation"] = "image"
610
+ with HDF5File(sa_delta_beta_results_url.file_path(), mode="a") as h5f:
611
+ nx_process = h5f.require_group(sa_delta_beta_results_url.data_path())
612
+ score_roi_grp = nx_process.require_group("score_roi")
613
+ for db, roi in score_rois.items():
614
+ score_roi_grp[str(db)] = roi
615
+ score_roi_grp[str(db)].attrs["interpretation"] = "image"
623
616
 
624
617
  @staticmethod
625
618
  def program_name():
@@ -637,73 +630,72 @@ class SADeltaBetaTask(
637
630
  return "Semi automatic center of rotation / axis calculation"
638
631
 
639
632
  @staticmethod
640
- def process_to_tomwer_processes(scan):
641
- if scan.process_file is not None:
642
- entry = "entry"
643
- if isinstance(scan, NXtomoScan):
644
- entry = scan.entry
633
+ def get_results_url(scan):
634
+ return DataUrl(
635
+ file_path=scan.get_relative_file(
636
+ os.path.join(DEFAULT_RECONS_FOLDER, "tomwer_sadelta_beta.h5")
637
+ ),
638
+ data_path=scan.entry or "entry",
639
+ scheme="silx",
640
+ )
645
641
 
646
- db = None
647
- if scan.sa_delta_beta_params is not None:
648
- db = scan.sa_delta_beta_params.selected_delta_beta_value
642
+ @staticmethod
643
+ def save_results_to_disk(scan):
644
+ if scan.saaxis_params.scores in (None, {}):
645
+ return
649
646
 
650
- process_index = scan.pop_process_index()
651
- try:
652
- with scan.acquire_process_file_lock():
653
- Task._register_process(
654
- process_file=scan.process_file,
655
- entry=entry,
656
- results={"delta_beta": db if db is not None else "-"},
657
- configuration=scan.sa_delta_beta_params.to_dict(),
658
- process_index=process_index,
659
- overwrite=True,
660
- process=SADeltaBetaTask,
661
- )
662
- SADeltaBetaTask._extends_results(
663
- scan=scan, entry=entry, process_index=process_index
664
- )
665
- except Exception as e:
666
- _logger.warning(
667
- f"Fail to register process of with index {process_index}. Reason is {e}"
647
+ results_url = SADeltaBetaTask.get_results_url(scan=scan)
648
+ # save it to the file
649
+ with HDF5File(results_url.file_path(), mode="w") as h5f:
650
+ nx_process = h5f.require_group(results_url.data_path())
651
+ if "NX_class" not in nx_process.attrs:
652
+ nx_process.attrs["NX_class"] = "NXprocess"
653
+
654
+ results = nx_process.require_group("results")
655
+
656
+ for cor, (url, score) in scan.sa_delta_beta_params.scores.items():
657
+ results_db = results.require_group(str(cor))
658
+ for method in ScoreMethod:
659
+ if method is ScoreMethod.TOMO_CONSISTENCY:
660
+ continue
661
+ results_db[method.value] = score.get(method)
662
+
663
+ link_path = os.path.relpath(
664
+ url.file_path(),
665
+ os.path.dirname(results_url.file_path()),
666
+ )
667
+ results_db["reconstructed_slice"] = h5py.ExternalLink(
668
+ link_path, url.data_path()
668
669
  )
669
-
670
- return process_index
671
670
 
672
671
  @staticmethod
673
- def _extends_results(scan, entry, process_index):
674
- process_file = scan.process_file
675
- process_name = "tomwer_process_" + str(process_index)
672
+ def load_results_from_disk(scan):
673
+ results_url = SADeltaBetaTask.get_results_url(scan=scan)
674
+ process_file = results_url.file_path()
676
675
 
677
- if scan.sa_delta_beta_params.scores in (None, {}):
678
- return
679
-
680
- def get_process_path():
681
- return "/".join((entry or "entry", process_name))
676
+ if process_file is None or not os.path.exists(process_file):
677
+ _logger.warning(
678
+ "Unable to find process file. Unable to read " "existing processing"
679
+ )
680
+ return None, None
682
681
 
683
- # save it to the file
684
- with FileLockerManager().get_lock(process_file):
685
- # needs an extra lock for multiprocessing
686
-
687
- with HDF5File(process_file, mode="a") as h5f:
688
- nx_process = h5f.require_group(get_process_path())
689
- if "NX_class" not in nx_process.attrs:
690
- nx_process.attrs["NX_class"] = "NXprocess"
691
-
692
- results = nx_process.require_group("results")
693
- for cor, (url, score) in scan.sa_delta_beta_params.scores.items():
694
- results_db = results.require_group(str(cor))
695
- for method in ScoreMethod:
696
- if method is ScoreMethod.TOMO_CONSISTENCY:
697
- continue
698
- results_db[method.value] = score.get(method)
699
-
700
- link_path = os.path.relpath(
701
- url.file_path(),
702
- os.path.dirname(process_file),
703
- )
704
- results_db["reconstructed_slice"] = h5py.ExternalLink(
705
- link_path, url.data_path()
682
+ try:
683
+ with EntryReader(results_url) as h5f_entry_node:
684
+ scores = core_utils.get_scores(h5f_entry_node)
685
+ if (
686
+ "results" in h5f_entry_node
687
+ and "delta_beta" in h5f_entry_node["results"]
688
+ ):
689
+ selected = h5py_read_dataset(
690
+ h5f_entry_node["results"]["delta_beta"]
706
691
  )
692
+ else:
693
+ _logger.warning(f"no results found for {scan}")
694
+ selected = None
695
+ return scores, selected
696
+ except ValueError:
697
+ _logger.warning(f"Data path ({results_url.data_path()}) not found")
698
+ return None, None
707
699
 
708
700
  def cancel(self):
709
701
  """
@@ -0,0 +1,37 @@
1
+ import os
2
+ from tomwer.core.process.reconstruction.params_cache import (
3
+ _CACHE,
4
+ _CACHE_SIZE,
5
+ save_reconstruction_parameters_to_cache,
6
+ clear_reconstruction_parameters_cache,
7
+ )
8
+ from tomwer.core.utils.scanutils import MockNXtomo
9
+
10
+
11
+ def test_cache(tmp_path):
12
+ nxtomos = [
13
+ MockNXtomo(
14
+ scan_path=os.path.join(tmp_path, f"my_nxtomo_{i_scan}"),
15
+ n_proj=10,
16
+ ).scan
17
+ for i_scan in range(31)
18
+ ]
19
+ new_nxtomo = MockNXtomo(
20
+ scan_path=os.path.join(tmp_path, "my_nxtomo_99"),
21
+ n_proj=10,
22
+ ).scan
23
+
24
+ clear_reconstruction_parameters_cache()
25
+ # test saving it in the original order
26
+ [save_reconstruction_parameters_to_cache(scan=scan) for scan in nxtomos]
27
+ assert len(_CACHE) == _CACHE_SIZE
28
+ assert _CACHE == {
29
+ nxtomo.get_identifier().to_str(): (None, None) for nxtomo in nxtomos[1:]
30
+ }
31
+
32
+ # try updating the next last one to make sure it won't be removed
33
+ save_reconstruction_parameters_to_cache(scan=nxtomos[1])
34
+ save_reconstruction_parameters_to_cache(scan=new_nxtomo)
35
+ assert nxtomos[1].get_identifier().to_str() in _CACHE
36
+ assert nxtomos[2].get_identifier().to_str() not in _CACHE
37
+ clear_reconstruction_parameters_cache()
@@ -7,7 +7,6 @@ import logging
7
7
 
8
8
  import tomwer.version
9
9
  from tomwer.core.process.task import Task
10
- from tomwer.core.scan.edfscan import EDFTomoScan
11
10
  from tomwer.core.scan.scanbase import TomwerScanBase
12
11
  from tomwer.core.scan.scanfactory import ScanFactory
13
12
  from tomwer.core.utils.scanutils import data_identifier_to_scan
@@ -40,24 +39,6 @@ class PythonScript(
40
39
  out_data = data_identifier_to_scan(interpreter.locals.get("out_data"))
41
40
  out_volume = data_identifier_to_scan(interpreter.locals.get("out_volume"))
42
41
 
43
- # register process
44
- if isinstance(scan, EDFTomoScan):
45
- entry = None
46
- else:
47
- entry = scan.entry
48
-
49
- try:
50
- self.register_process(
51
- process_file=scan.process_file,
52
- entry=entry,
53
- configuration={"scriptText": self.get_configuration()["scriptText"]},
54
- results=None,
55
- process_index=scan.pop_process_index(),
56
- overwrite=True,
57
- )
58
- except Exception as e:
59
- _logger.error("Fail to register process. Error is " + str(e))
60
-
61
42
  if out_data is not None and self.get_input_value("serialize_output_data", True):
62
43
  self.outputs.data = out_data.to_dict()
63
44
  else: