tomwer 1.4.4__py3-none-any.whl → 1.4.5__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.
@@ -15,6 +15,8 @@ import sys
15
15
  import numpy
16
16
  from silx.io.url import DataUrl
17
17
  from silx.io.utils import open as open_hdf5
18
+ from silx.gui.utils import concurrent
19
+
18
20
  from sluurp.executor import submit as submit_to_slurm_cluster
19
21
  from sluurp.job import SBatchScriptJob
20
22
  from tomoscan.io import HDF5File
@@ -41,6 +43,8 @@ from tomwer.core.scan.nxtomoscan import NXtomoScan
41
43
  from tomwer.core.scan.scanbase import TomwerScanBase
42
44
  from tomwer.core.utils.slurm import get_slurm_script_name, is_slurm_available
43
45
  from tomwer.core.volume.volumefactory import VolumeFactory
46
+ from tomwer.core.resourcemanager import HDF5VolumeManager
47
+ from tomwer.core.volume.hdf5volume import HDF5VolumeIdentifier
44
48
 
45
49
  from . import settings, utils
46
50
 
@@ -279,25 +283,43 @@ class _NabuBaseReconstructor:
279
283
  success=True,
280
284
  config=config_to_dump,
281
285
  )
282
- elif self.target is Target.LOCAL:
283
- _logger.info(f"run {info} for {self.scan} with {config_to_dump}")
284
- return self._run_nabu_locally(
285
- conf_file=config_file,
286
- file_format=file_format,
287
- config_to_dump=config_to_dump,
288
- axis=config_to_dump["reconstruction"].get("slice_plane", "XY"),
289
- )
290
- elif self.target is Target.SLURM:
291
- _logger.info(
292
- f"run {info} on slurm for {self.scan.path} with {config_to_dump}"
293
- )
294
- return self._run_nabu_on_slurm(
295
- conf_file=config_file,
296
- config_to_dump=config_to_dump,
297
- cluster_config=self.cluster_config.to_dict(),
298
- process_name=process_name,
299
- info=info,
300
- )
286
+ elif self.target in (Target.LOCAL, Target.SLURM):
287
+ axis = config_to_dump["reconstruction"].get("slice_plane", "XY")
288
+ if file_format in ("hdf5", "h5", "hdf"):
289
+ vol_identifiers = utils.get_recons_volume_identifier(
290
+ file_prefix=config_to_dump["output"]["file_prefix"],
291
+ location=config_to_dump["output"]["location"],
292
+ slice_index=None,
293
+ scan=self.scan,
294
+ file_format=file_format,
295
+ axis=axis,
296
+ )
297
+ # release potential resource lockers (like the HDF5 volume viewer)
298
+ for vol_identifier in vol_identifiers:
299
+ if isinstance(vol_identifier, HDF5VolumeIdentifier):
300
+ concurrent.submitToQtMainThread(
301
+ HDF5VolumeManager.release_resource,
302
+ vol_identifier.file_path,
303
+ )
304
+ if self.target is Target.LOCAL:
305
+ _logger.info(f"run {info} for {self.scan} with {config_to_dump}")
306
+ return self._run_nabu_locally(
307
+ conf_file=config_file,
308
+ file_format=file_format,
309
+ config_to_dump=config_to_dump,
310
+ axis=axis,
311
+ )
312
+ elif self.target is Target.SLURM:
313
+ _logger.info(
314
+ f"run {info} on slurm for {self.scan.path} with {config_to_dump}"
315
+ )
316
+ return self._run_nabu_on_slurm(
317
+ conf_file=config_file,
318
+ config_to_dump=config_to_dump,
319
+ cluster_config=self.cluster_config.to_dict(),
320
+ process_name=process_name,
321
+ info=info,
322
+ )
301
323
  else:
302
324
  raise ValueError(f"{self.target} is not recognized as a valid target")
303
325
 
@@ -362,7 +384,7 @@ class _NabuBaseReconstructor:
362
384
  self._process.kill()
363
385
  outs, errs = self._process.communicate()
364
386
 
365
- recons_urls = utils.get_recons_volume_identifier(
387
+ recons_vol_identifiers = utils.get_recons_volume_identifier(
366
388
  file_prefix=config_to_dump["output"]["file_prefix"],
367
389
  location=config_to_dump["output"]["location"],
368
390
  slice_index=None,
@@ -372,7 +394,7 @@ class _NabuBaseReconstructor:
372
394
  )
373
395
  return ResultsLocalRun(
374
396
  success=not nabu_std_err_has_error(errs),
375
- results_identifiers=recons_urls,
397
+ results_identifiers=recons_vol_identifiers,
376
398
  std_out=outs,
377
399
  std_err=errs,
378
400
  config=config_to_dump, # config_slices,
@@ -12,6 +12,7 @@ from nabu.pipeline.fullfield.nabu_config import (
12
12
  )
13
13
  from silx.utils.enum import Enum as _Enum
14
14
 
15
+ from tomoscan.identifier import VolumeIdentifier
15
16
  import tomwer.version
16
17
  from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
17
18
  from tomwer.core.scan.edfscan import EDFTomoScan
@@ -100,7 +101,7 @@ def get_recons_volume_identifier(
100
101
  scan: TomwerScanBase,
101
102
  slice_index: int | None,
102
103
  axis: NabuPlane,
103
- ) -> tuple:
104
+ ) -> tuple[VolumeIdentifier]:
104
105
  """
105
106
  return tuple of DataUrl for existings slices
106
107
  """
@@ -160,19 +161,6 @@ def get_recons_volume_identifier(
160
161
  ),
161
162
  )
162
163
 
163
- # case of the multitiff. Not handled by tomwer
164
- # elif file_format == "tiff":
165
- # # for single frame tiff nabu uses another convention by saving it 'directly'.
166
- # volumes = (
167
- # MultiTIFFVolume(
168
- # file_path=os.path.join(
169
- # location,
170
- # file_prefix,
171
- # ".".join([file_prefix, file_format]),
172
- # ),
173
- # ),
174
- # )
175
-
176
164
  else:
177
165
  raise ValueError(f"file format not managed: {file_format}")
178
166
 
@@ -0,0 +1,33 @@
1
+ class BaseResourceObserver:
2
+ """base class of the resource observer"""
3
+
4
+ def release_resource(self, resource):
5
+ raise NotImplementedError("Base class")
6
+
7
+
8
+ class _DummyResourceManager:
9
+ """
10
+ Simple resource manager. It holds a set of observer tha must release a resource when requested
11
+ Observers must implement the 'BaseResourceObserver'
12
+ """
13
+
14
+ def __init__(self):
15
+ self._observers = set()
16
+
17
+ def register(self, observer):
18
+ """Register a process to be notified when the resource should be released."""
19
+ if observer not in self._observers:
20
+ self._observers.add(observer)
21
+
22
+ def unregister(self, observer):
23
+ """Unregister a process so it won't be notified anymore."""
24
+ if observer in self._observers:
25
+ self._observers.remove(observer)
26
+
27
+ def release_resource(self, resource: str):
28
+ """Force all observer to release the given resource"""
29
+ for observer in self._observers:
30
+ observer.release_resource(resource)
31
+
32
+
33
+ HDF5VolumeManager = _DummyResourceManager()
@@ -211,7 +211,7 @@ class _PositionInfoWidget(qt.QWidget):
211
211
  else:
212
212
  value = float(self._relativePositionQLE.text())
213
213
  # make sure we only emit the signal if the value changed (and when the Qline has been edited).
214
- if self._axis_params.relative_cor_value is None or (
214
+ if isinstance(self._axis_params.relative_cor_value, (type(None), str)) or (
215
215
  self._axis_params is not None
216
216
  and not numpy.isclose(
217
217
  value, self._axis_params.relative_cor_value, atol=1e-3
@@ -6,6 +6,8 @@ import h5py
6
6
 
7
7
  import numpy
8
8
  import numpy.lib.npyio
9
+
10
+ import os
9
11
  import silx
10
12
  from silx.gui import qt
11
13
  from silx.gui.colors import Colormap
@@ -18,6 +20,7 @@ from tomwer.core.volume.volumefactory import VolumeFactory
18
20
  from tomwer.core.scan.scanbase import TomwerScanBase
19
21
  from tomwer.gui.visualization.reconstructionparameters import ReconstructionParameters
20
22
  from tomwer.core.volume.hdf5volume import HDF5Volume
23
+ from tomwer.core.resourcemanager import BaseResourceObserver, HDF5VolumeManager
21
24
  from tomoscan.identifier import VolumeIdentifier
22
25
 
23
26
  from silx.gui.widgets.WaitingOverlay import WaitingOverlay
@@ -215,9 +218,9 @@ class _TomoApplicationContext(DataViewHooks):
215
218
  return self.__defaultColormapDialog
216
219
 
217
220
 
218
- class VolumeViewer(qt.QMainWindow):
221
+ class VolumeViewer(qt.QMainWindow, BaseResourceObserver):
219
222
  def __init__(self, parent):
220
- qt.QMainWindow.__init__(self, parent)
223
+ super().__init__(parent)
221
224
 
222
225
  self._volume_loaded_in_background = (None, None)
223
226
  # store the volume loaded in the background and the thread used for it as (volume_identifier, thread)
@@ -259,6 +262,8 @@ class VolumeViewer(qt.QMainWindow):
259
262
  loading data on the fly and avoid loading everything into memory for
260
263
  hdf5."""
261
264
  self.__last_mode = None
265
+ # register the viewer as observer of the HDF5 volume (handle resource conflict)
266
+ HDF5VolumeManager.register(self)
262
267
 
263
268
  def _close_h5_file(self):
264
269
  if self._h5_file is not None:
@@ -266,9 +271,21 @@ class VolumeViewer(qt.QMainWindow):
266
271
  self._h5_file = None
267
272
 
268
273
  def close(self):
274
+ HDF5VolumeManager.unregister(self)
269
275
  self._close_h5_file()
270
276
  super().close()
271
277
 
278
+ def release_resource(self, resource: str):
279
+ if self._h5_file is not None and resource in (
280
+ self._h5_file.filename,
281
+ os.path.abspath(self._h5_file.filename),
282
+ ):
283
+ _logger.warning(
284
+ f"{resource} about to be overwrite. Closing resource and cleaning plot."
285
+ )
286
+ self._close_h5_file()
287
+ self.clear()
288
+
272
289
  def setScan(self, scan):
273
290
  self.clear()
274
291
  if scan is None:
@@ -276,7 +293,6 @@ class VolumeViewer(qt.QMainWindow):
276
293
 
277
294
  elif len(scan.latest_vol_reconstructions) == 0:
278
295
  _logger.warning(f"No reconstructed volume for {scan}")
279
- self.clear()
280
296
  self._infoWidget.setScan(scan)
281
297
  else:
282
298
  self._set_volumes(volumes=scan.latest_vol_reconstructions)
tomwer/version.py CHANGED
@@ -77,7 +77,7 @@ RELEASE_LEVEL_VALUE = {
77
77
 
78
78
  MAJOR = 1
79
79
  MINOR = 4
80
- MICRO = 4
80
+ MICRO = 5
81
81
  RELEV = "final" # <16
82
82
  SERIAL = 0 # <16
83
83
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tomwer
3
- Version: 1.4.4
3
+ Version: 1.4.5
4
4
  Summary: "tomography workflow tools"
5
5
  Home-page: https://gitlab.esrf.fr/tomotools/tomwer
6
6
  Author: Henri Payno, Pierre Paleo, Pierre-Olivier Autran, Jérôme Lesaint, Alessandro Mirone
@@ -220,7 +220,7 @@ orangecontrib/tomwer/widgets/visualization/tests/__init__.py,sha256=47DEQpj8HBSa
220
220
  tomwer/__init__.py,sha256=GeLSeY4__z-HQZu1y4ptZ5Y1OeXFvG8kuEwWXhkeaMA,360
221
221
  tomwer/__main__.py,sha256=7tCADiS4u7k1PCxFhlRAcYSIOpxQTGUTx8sCEQ-hi1E,8707
222
222
  tomwer/utils.py,sha256=7h7dEgKAEUmQ43jkULvC1B9Adl55nkCty-SEKUKCl4U,7008
223
- tomwer/version.py,sha256=cQn0hp7H0RGoblTK9Od0_A4QCnVaVE5G-t2RThewbMg,4386
223
+ tomwer/version.py,sha256=YCgU5UeQQFVVtrqoIyPtoYMjDfnF7xbfD1Fop0kLlSA,4386
224
224
  tomwer/app/__init__.py,sha256=RYMB2YhbQaoMXC8W-oOyfZ_Y1vmHD7L13YkKeAMuShM,85
225
225
  tomwer/app/axis.py,sha256=OhDgMj_gS-45PnjKBTyOCOkmZ1Iy-Tb6Dj66mzQg0sU,5827
226
226
  tomwer/app/canvas.py,sha256=sM368nniUwbQXLA-oNCg1iNwMMol_ZGTKbiw8WsC4yw,1539
@@ -256,6 +256,7 @@ tomwer/app/stitching/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
256
256
  tomwer/app/stitching/common.py,sha256=TCXNnAz2MSJrrogB5iWptktxq-g5ED2FUt_jMnDXpnQ,14723
257
257
  tomwer/core/__init__.py,sha256=ry3BZxaZzsbjymW1wqPcKROzJO9ePkiiqWp1JRVOrS8,72
258
258
  tomwer/core/futureobject.py,sha256=YQE6zROyDFu2PYBI7hxZKpn-K_FqZQ9xGSIyqMErK5U,5114
259
+ tomwer/core/resourcemanager.py,sha256=VLNnVodMa-HOMZhN2qpUR_L6phJ8IHPUEPYMxuW6VHg,1067
259
260
  tomwer/core/settings.py,sha256=57qD44LU_3eB50rD7RHdg5nBweiHerzWbXHcBUna6gY,4089
260
261
  tomwer/core/signal.py,sha256=I5TUcyeBZzrEh1SFGs-ylJSL1aBs41ZFb3IJo3O_55c,6115
261
262
  tomwer/core/tomwer_object.py,sha256=rIaD1QlN3Q0cR5h9Sap1Whn4lawu5z9zZ1KspdhYbg0,2023
@@ -334,14 +335,14 @@ tomwer/core/process/reconstruction/darkref/settings.py,sha256=35jliuOIjMKTOJjgn4
334
335
  tomwer/core/process/reconstruction/nabu/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
335
336
  tomwer/core/process/reconstruction/nabu/castvolume.py,sha256=4VEVnJxWfG8_Ku2uhUSQAgGfvP_08mXswmC3bHU7E4M,9317
336
337
  tomwer/core/process/reconstruction/nabu/helical.py,sha256=gauUkoPiShvnvMQrCQXv28g0yLe-GceML5kYMSXmNIg,1997
337
- tomwer/core/process/reconstruction/nabu/nabucommon.py,sha256=s1KxEzHQJ09JEWP3_EvKFe51k1boi_a8YRlbs3TppdE,23338
338
+ tomwer/core/process/reconstruction/nabu/nabucommon.py,sha256=-rXMJmLL3e7BCF4keT7JcKmC5SuJQsCrvIDCYcbum48,24519
338
339
  tomwer/core/process/reconstruction/nabu/nabuscores.py,sha256=e5tRG1QtmVAdXb8KHMTMtBXA3KQXqKKcqipY2HzMURg,25275
339
340
  tomwer/core/process/reconstruction/nabu/nabuslices.py,sha256=WAmNlfyRWL0zhEE8jMjMg7WyzPM4BcBA6bWpaH8O53A,32101
340
341
  tomwer/core/process/reconstruction/nabu/nabuvolume.py,sha256=Fn0tkPDTDJQaMEJA4LzpPp0ZtG4MIu9YN82-jesxRKo,20052
341
342
  tomwer/core/process/reconstruction/nabu/plane.py,sha256=366gWprWw8Rlob8jsMn753CqgudruvvVauU0ihH2lU4,400
342
343
  tomwer/core/process/reconstruction/nabu/settings.py,sha256=3AJpxVQbJziw4v6F26Ppz8Q9vc9ZNepTWygqpCAbIEM,955
343
344
  tomwer/core/process/reconstruction/nabu/target.py,sha256=59BbpzpBRVKEpZowcZVgdAj1GLKZGVJ52s3XA7ouLPs,122
344
- tomwer/core/process/reconstruction/nabu/utils.py,sha256=MvGMeAKrpSzScvRowe2ZbyQyNLj80vxm3jk-ldMMPEU,16519
345
+ tomwer/core/process/reconstruction/nabu/utils.py,sha256=ymORZjJR7YkQ0VBujDyptF0xXzkj1dCwo29NjXvhA2E,16140
345
346
  tomwer/core/process/reconstruction/nabu/test/test_castvolume.py,sha256=v7USCU3z0zeW4TPs-slNJJei6t6B_UeqeJG5MV9qRII,3881
346
347
  tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py,sha256=8HpR_1iLkE32GYYaOyS84SR7_5nh1e48E3W4N34666g,15347
347
348
  tomwer/core/process/reconstruction/nabu/test/test_nabunormalization.py,sha256=5rHDwUROEBlsEFsZoy8mmcdRpziEetF9g_oFyxlvS6k,6010
@@ -545,7 +546,7 @@ tomwer/gui/reconstruction/axis/AxisSettingsWidget.py,sha256=7GpHteE2j9RUo-jUQoJd
545
546
  tomwer/gui/reconstruction/axis/AxisWidget.py,sha256=nkORZHLo8D3Sk8j-8QVr9l3Qse66s-Nv-tB6kCkSMTY,19794
546
547
  tomwer/gui/reconstruction/axis/CalculationWidget.py,sha256=E9zwJ2dNnc7KGH1QHRZE2eElIzj_r4GbPCIG_hn2yhw,8628
547
548
  tomwer/gui/reconstruction/axis/CompareImages.py,sha256=jqzlMBU_tfIdR1yHuZa8Avt8Te0EPBkjI6R4TY6kIlw,11425
548
- tomwer/gui/reconstruction/axis/ControlWidget.py,sha256=DsBPFIEZCva-JPUFxORjkAnoYfgb5udfJ71W-fCwgRY,10686
549
+ tomwer/gui/reconstruction/axis/ControlWidget.py,sha256=w2kNLuIhQhGT3KpEYWWq4XJks3Kr7R2aOPCTKz4je4U,10709
549
550
  tomwer/gui/reconstruction/axis/EstimatedCORWidget.py,sha256=dL9SCjPEZ7MQLGZP0gZARb-rxD8YYSl-gcFyuN14jwg,17081
550
551
  tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py,sha256=Hq8o6X5-iVMqltGcpy2E5OpCP5nNV353Mepsf_R7zVY,4434
551
552
  tomwer/gui/reconstruction/axis/InputWidget.py,sha256=UhEWL3aJG56PfkI7DKw-sBd6hDsRJ2NnQ0XN0nBmM6g,13052
@@ -668,7 +669,7 @@ tomwer/gui/visualization/scanoverview.py,sha256=boXasH759jc8p9v43nFqq6oxFGDMn8gg
668
669
  tomwer/gui/visualization/sinogramviewer.py,sha256=M91xw63ptfG1erPt6jvFH5uqmV6KUm1B4xreco6Ixto,8380
669
670
  tomwer/gui/visualization/tomoobjoverview.py,sha256=8tsVhTZw0upDSYzE1W8VXCWMBmSFcEP7SlcGA6Nl6ig,1995
670
671
  tomwer/gui/visualization/volumeoverview.py,sha256=k0OLdw5dvbDlWFnk6I8TlrJu03dmKToCZVEtmAh_U9M,2496
671
- tomwer/gui/visualization/volumeviewer.py,sha256=nT9GXMFZ86Hy6ppCJB_HnE8jFgIyvEmUnPPY1JZau1A,17007
672
+ tomwer/gui/visualization/volumeviewer.py,sha256=CVfRj_azmrfoSztjX3l6nnQ9Yoyk9yhNbREoXRRq7eY,17648
672
673
  tomwer/gui/visualization/diffviewer/__init__.py,sha256=rZ7qOTfAChU3FouCdkZllXT9ZZqTdo1XhLZMfmOqUAE,39
673
674
  tomwer/gui/visualization/diffviewer/diffviewer.py,sha256=_MOApAnImO7cYg0-Oz8EKfJt0hWeDqusYLZ_gBrRRdk,20556
674
675
  tomwer/gui/visualization/diffviewer/shiftwidget.py,sha256=7gD_mo9P7HXklD416BScUnrQNDDqXkItgkzehqBam00,19608
@@ -903,9 +904,9 @@ tomwer/tests/orangecontrib/tomwer/widgets/visualization/tests/test_volume_viewer
903
904
  tomwer/tests/test_ewoks/test_conversion.py,sha256=a8cEWbErXiFCAkaapi0jeEoRKYxcFQCoa-Jr_u77_OM,3656
904
905
  tomwer/tests/test_ewoks/test_single_node_execution.py,sha256=YBUHfiAnkciv_kjj7biC5fOs7c7ofNImM_azGMn4LZM,2813
905
906
  tomwer/tests/test_ewoks/test_workflows.py,sha256=Eq80eexf5NVL7SzvwctLOaUeuQ8V3vDiFiHgbJA4Yb8,4871
906
- tomwer-1.4.4.dist-info/LICENSE,sha256=62p1wL0n9WMTu8x2YDv0odYgTqeSvTd9mQ0v6Mq7lzE,1876
907
- tomwer-1.4.4.dist-info/METADATA,sha256=rX-5hSdlbZ--HdznnGl7KCiDSBycJgqfzwxurDQeYFU,13377
908
- tomwer-1.4.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
909
- tomwer-1.4.4.dist-info/entry_points.txt,sha256=py3ZUWvGnWGc5c7Yhw_uBTm8Fmew0BDw3aQZnWMBNZI,500
910
- tomwer-1.4.4.dist-info/top_level.txt,sha256=Yz5zKh0FPiImtzHYcPuztG1AO8-6KEpUWgoChGbA0Ys,21
911
- tomwer-1.4.4.dist-info/RECORD,,
907
+ tomwer-1.4.5.dist-info/LICENSE,sha256=62p1wL0n9WMTu8x2YDv0odYgTqeSvTd9mQ0v6Mq7lzE,1876
908
+ tomwer-1.4.5.dist-info/METADATA,sha256=0NdM0A0KYCcrCLxW5E546hD9VL2otACgkkf8UvJH6ao,13377
909
+ tomwer-1.4.5.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
910
+ tomwer-1.4.5.dist-info/entry_points.txt,sha256=py3ZUWvGnWGc5c7Yhw_uBTm8Fmew0BDw3aQZnWMBNZI,500
911
+ tomwer-1.4.5.dist-info/top_level.txt,sha256=Yz5zKh0FPiImtzHYcPuztG1AO8-6KEpUWgoChGbA0Ys,21
912
+ tomwer-1.4.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5