From 6cac090aac3d55554d2d1007901cc9cf834adc88 Mon Sep 17 00:00:00 2001
From: payno <henri.payno@esrf.fr>
Date: Thu, 22 Feb 2024 15:04:33 +0100
Subject: [PATCH] Merge branch 'fix_self_referenced_vs' into '1.2'

VDS: fix self-referencing VDS

See merge request tomotools/nxtomo!29

(cherry picked from commit e24e18c8aa82753900bba8a444646c360d4088f8)

8a182cb9 VDS: fix self-referencing VDS
---
 nxtomo/io.py                            | 17 +++++++++++++----
 nxtomo/nxobject/nxobject.py             |  4 +++-
 nxtomo/nxobject/test/test_nxdetector.py |  6 +++---
 nxtomo/utils/frameappender.py           |  4 +++-
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/nxtomo/io.py b/nxtomo/io.py
index 3da3526..8a4ae5c 100644
--- a/nxtomo/io.py
+++ b/nxtomo/io.py
@@ -43,7 +43,7 @@ def check_virtual_sources_exist(fname, data_path):
     return True
 
 
-def from_data_url_to_virtual_source(url: DataUrl) -> tuple:
+def from_data_url_to_virtual_source(url: DataUrl, target_path: Optional[str]) -> tuple:
     """
     convert a DataUrl to a set (as tuple) of h5py.VirtualSource
 
@@ -74,9 +74,14 @@ def from_data_url_to_virtual_source(url: DataUrl) -> tuple:
                 original_data_shape[-1],
             )
 
-    vs = h5py.VirtualSource(
-        url.file_path(), url.data_path(), shape=vs_shape, dtype=data_type
-    )
+    if target_path is not None and (
+        target_path == url.file_path()
+        or os.path.abspath(target_path) == url.file_path()
+    ):
+        file_path = "."
+    else:
+        file_path = url.file_path()
+    vs = h5py.VirtualSource(file_path, url.data_path(), shape=vs_shape, dtype=data_type)
 
     if url.data_slice() is not None:
         vs.sel = selection.select(original_data_shape, url.data_slice())
@@ -133,6 +138,10 @@ def to_target_rel_path(file_path: str, target_path: str) -> str:
     :return: relative path of file_path compared to target_path
     :rtype: str
     """
+    if file_path == target_path or os.path.abspath(file_path) == os.path.abspath(
+        target_path
+    ):
+        return "."
     file_path = os.path.abspath(file_path)
     target_path = os.path.abspath(target_path)
     path = os.path.relpath(file_path, os.path.dirname(target_path))
diff --git a/nxtomo/nxobject/nxobject.py b/nxtomo/nxobject/nxobject.py
index 1b5163a..f0e1399 100644
--- a/nxtomo/nxobject/nxobject.py
+++ b/nxtomo/nxobject/nxobject.py
@@ -261,7 +261,9 @@ class NXobject:
                 dataset_keys = v_sources_or_data_urls
                 for v_source_or_data_url in dataset_keys:
                     if isinstance(v_source_or_data_url, DataUrl):
-                        vs = from_data_url_to_virtual_source(v_source_or_data_url)[0]
+                        vs = from_data_url_to_virtual_source(
+                            v_source_or_data_url, target_path=master_vds_file
+                        )[0]
                     else:
                         assert isinstance(
                             v_source_or_data_url, h5py.VirtualSource
diff --git a/nxtomo/nxobject/test/test_nxdetector.py b/nxtomo/nxobject/test/test_nxdetector.py
index f09a340..137fae4 100644
--- a/nxtomo/nxobject/test/test_nxdetector.py
+++ b/nxtomo/nxobject/test/test_nxdetector.py
@@ -171,7 +171,7 @@ def test_nx_detector_with_virtual_source():
 
             # check virtual dataset is composed of relative links
             for vs_info in dataset.virtual_sources():
-                assert vs_info.file_name.startswith("./")
+                assert vs_info.file_name.startswith(".")
         assert cwd == os.getcwd()
 
     # check concatenation
@@ -224,7 +224,7 @@ def test_nx_detector_with_local_urls():
                 )
             # check virtual dataset is composed of relative links
             for vs_info in dataset.virtual_sources():
-                assert vs_info.file_name.startswith("./")
+                assert vs_info.file_name.startswith(".")
         assert cwd == os.getcwd()
 
     # check concatenation
@@ -288,7 +288,7 @@ def test_nx_detector_with_external_urls():
                     )
             # check virtual dataset is composed of relative links
             for vs_info in dataset.virtual_sources():
-                assert vs_info.file_name.startswith("./")
+                assert vs_info.file_name.startswith(".")
 
         assert cwd == os.getcwd()
         # check concatenation
diff --git a/nxtomo/utils/frameappender.py b/nxtomo/utils/frameappender.py
index ec75955..d9971e4 100644
--- a/nxtomo/utils/frameappender.py
+++ b/nxtomo/utils/frameappender.py
@@ -302,7 +302,9 @@ class FrameAppender:
             )
 
             with cwd_context(os.path.dirname(self.file_path)):
-                vs, vs_shape, data_type = from_data_url_to_virtual_source(url)
+                vs, vs_shape, data_type = from_data_url_to_virtual_source(
+                    url, target_path=self.file_path
+                )
                 layout = h5py.VirtualLayout(shape=vs_shape, dtype=data_type)
                 layout[:] = vs
                 h5s.create_virtual_dataset(self.data_path, layout)
-- 
GitLab