Skip to content

Commit 1bc1899

Browse files
Fix Incorrect Sample Shape In Added SANS Runs (#39389)
This pulls the following into `ornl-next` * #39234 * #39365 --------- Co-authored-by: Caila Finn <47181718+cailafinn@users.noreply.github.com>
1 parent 86d6e6b commit 1bc1899

File tree

9 files changed

+100
-22
lines changed

9 files changed

+100
-22
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
39129303843e41fa060cc4b50413ff3a
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ee8bbab4b40dbd3d03eb7ea6978347b3

Testing/SystemTests/tests/framework/ISIS/SANS/WORKFLOWS/SANSUtilityTest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class SANSUtilityTest(systemtesting.MantidSystemTest):
2727
def runTest(self):
2828
# created after issue reported in #8156
2929
ws = Load("LOQ54432")
30-
self.assertTrue("LOQ/LOQ54432.raw" in unixLikePathFromWorkspace(ws))
30+
self.assertTrue("LOQ54432.raw" in unixLikePathFromWorkspace(ws))
3131
ws = Load("LOQ99618.RAW")
3232
self.assertTrue("LOQ/LOQ99618.RAW" in unixLikePathFromWorkspace(ws))
3333
add.add_runs(("LOQ54432", "LOQ54432"), "LOQ", ".raw")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- :ref:`ISIS_SANS_Sum_Runs_Tab-ref` in the ISIS SANS interface now maintains the sample properties
2+
(shape, thickness, height, and width) of the runs in the added output file.

scripts/SANS/SANSUtility.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -813,14 +813,17 @@ def is_nexus_file(file_name):
813813
full_file_path = FileFinder.findRuns(file_name)
814814
if hasattr(full_file_path, "__iter__"):
815815
file_name = full_file_path[0]
816-
is_nexus = True
817-
try:
818-
with h5.File(file_name, "r") as h5_file:
819-
keys = list(h5_file.keys())
820-
nexus_test = "raw_data_1" in keys or "mantid_workspace_1" in keys
821-
is_nexus = True if nexus_test else False
822-
except:
823-
is_nexus = False
816+
# quick check that is hdf5
817+
is_nexus = h5.is_hdf5(file_name)
818+
# fuller test looks at top level entries
819+
if is_nexus:
820+
try:
821+
keys = []
822+
with h5.File(file_name, "r") as h5_file:
823+
keys = list(h5_file.keys())
824+
is_nexus = bool("raw_data_1" in keys or "mantid_workspace_1" in keys)
825+
except:
826+
is_nexus = False
824827
return is_nexus
825828

826829

scripts/SANS/SANSadd2.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
SaveNexusProcessed,
2727
UnGroupWorkspace,
2828
)
29+
from sans.common.file_information import get_geometry_information_isis_nexus, convert_to_flag
2930
from SANSUtility import (
3031
AddOperation,
3132
transfer_special_sample_logs,
@@ -302,7 +303,8 @@ def _make_filename(entry, ext, inst):
302303
filename = inst + _pad_zero(run_num, inst) + ext
303304
except ValueError: # We don't have a run number, assume it's a valid filename
304305
filename = entry
305-
dummy, ext = os.path.splitext(filename)
306+
_, filename_ext = os.path.splitext(filename)
307+
ext = filename_ext if filename_ext else ext
306308

307309
return filename, ext
308310

@@ -378,6 +380,13 @@ def _load_ws(entry, ext, inst, ws_name, raw_types, period=_NO_INDIVIDUAL_PERIODS
378380

379381
if _is_type(ext, raw_types):
380382
LoadSampleDetailsFromRaw(InputWorkspace=ws_name, Filename=path + "/" + f_name)
383+
else:
384+
height, width, thickness, shape = get_geometry_information_isis_nexus(full_path)
385+
sample = mtd[ws_name].sample()
386+
sample.setGeometryFlag(convert_to_flag(shape))
387+
sample.setHeight(height)
388+
sample.setWidth(width)
389+
sample.setThickness(thickness)
381390

382391
# Change below when logs in Nexus files work file types of .raw need their log files to be copied too
383392
# if isType(ext, raw_types):

scripts/SANS/sans/common/file_information.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@
6161
HEIGHT = "height"
6262
THICKNESS = "thickness"
6363
SHAPE = "shape"
64-
CYLINDER = "CYLINDER"
65-
FLAT_PLATE = "FLAT PLATE"
66-
DISC = "DISC"
6764
GEOM_HEIGHT = "geom_height"
6865
GEOM_WIDTH = "geom_width"
6966
GEOM_THICKNESS = "geom_thickness"
@@ -304,6 +301,25 @@ def convert_to_flag(shape_string):
304301
return shape
305302

306303

304+
def convert_nexus_shape_to_sample_shape(nexus_shape: str) -> SampleShape | None:
305+
"""
306+
The ISIS nexus shape format can contain a space in flat plate.
307+
Handle this here for consistency with the other conversions.
308+
:param nexus_shape: The shape extracted from the ISIS nexus file.
309+
:return: The SampleShape version of the shape.
310+
"""
311+
nexus_shape = nexus_shape.upper()
312+
match nexus_shape:
313+
case "FLAT PLATE" | "FLATPLATE":
314+
return SampleShape.FLAT_PLATE
315+
case "DISC":
316+
return SampleShape.DISC
317+
case "CYLINDER":
318+
return SampleShape.CYLINDER
319+
case _:
320+
return None
321+
322+
307323
# ----------------------------------------------------------------------------------------------------------------------
308324
# Functions for ISIS Nexus
309325
# ----------------------------------------------------------------------------------------------------------------------
@@ -394,12 +410,12 @@ def is_raw_nexus_event_mode(file_name):
394410
|--some_group|
395411
|--Attribute: NX_class = NXevent_data
396412
"""
413+
is_event_mode = False
397414
with h5.File(file_name, "r") as h5_file:
398415
# Open first entry
399416
keys = list(h5_file.keys())
400417
first_entry = h5_file[keys[0]]
401418
# Open instrument group
402-
is_event_mode = False
403419
for value in list(first_entry.values()):
404420
if NX_CLASS in value.attrs and NX_EVENT_DATA == value.attrs[NX_CLASS].decode("utf-8"):
405421
is_event_mode = True
@@ -423,14 +439,7 @@ def get_geometry_information_isis_nexus(file_name):
423439
width = float(sample[WIDTH][0])
424440
thickness = float(sample[THICKNESS][0])
425441
shape_as_string = sample[SHAPE][0].upper().decode("utf-8")
426-
if shape_as_string == CYLINDER:
427-
shape = SampleShape.CYLINDER
428-
elif shape_as_string == FLAT_PLATE:
429-
shape = SampleShape.FLAT_PLATE
430-
elif shape_as_string == DISC:
431-
shape = SampleShape.DISC
432-
else:
433-
shape = None
442+
shape = convert_nexus_shape_to_sample_shape(shape_as_string)
434443
return height, width, thickness, shape
435444

436445

scripts/test/SANS/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pyunittest_add_test(
22
${CMAKE_CURRENT_SOURCE_DIR}
33
python.SANS
4+
SANSadd2Test.py
45
SANSBatchModeTest.py
56
SANSCentreFinderTest.py
67
SANSCommandInterfaceTest.py

scripts/test/SANS/SANSadd2Test.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Mantid Repository : https://github.com/mantidproject/mantid
2+
#
3+
# Copyright &copy; 2025 ISIS Rutherford Appleton Laboratory UKRI,
4+
# NScD Oak Ridge National Laboratory, European Spallation Source,
5+
# Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
# SPDX - License - Identifier: GPL - 3.0 +
7+
8+
import unittest
9+
from unittest.mock import patch
10+
11+
from SANS import SANSadd2
12+
from SANS.sans.common.enums import SampleShape
13+
from mantid.simpleapi import Load
14+
15+
16+
class TestSANSAddSampleMetadata(unittest.TestCase):
17+
def test_raw_files_get_correct_sample_info(self):
18+
result = SANSadd2.add_runs(("LOQ54432", "LOQ54432"), "LOQ", ".raw")
19+
assert result.startswith("The following file has been created:")
20+
assert result.endswith("LOQ54432-add.nxs")
21+
22+
# load the output file and verify it has the sample information
23+
ws = Load("LOQ54432-add.nxs")
24+
sample = ws.sample()
25+
self.assertEqual(3, sample.getGeometryFlag())
26+
self.assertEqual(8.0, sample.getHeight())
27+
self.assertEqual(8.0, sample.getWidth())
28+
self.assertAlmostEqual(1.035, sample.getThickness())
29+
30+
def test_raw_files_collect_sample_info_using_alg(self):
31+
with patch("SANS.SANSadd2.LoadSampleDetailsFromRaw") as mocked_load_sample:
32+
SANSadd2.add_runs(("LOQ54432", "LOQ54432"), "LOQ", ".raw")
33+
self.assertEqual(2, mocked_load_sample.call_count)
34+
35+
def test_isis_neuxs_files_get_correct_sample_info(self):
36+
result = SANSadd2.add_runs(["74014"], "LOQ", ".nxs", rawTypes=(".add", ".raw", ".s*"), lowMem=False)
37+
assert result.startswith("The following file has been created:")
38+
assert result.endswith("LOQ74014-add.nxs")
39+
40+
# load the output file and verify it has the sample information
41+
ws = Load("LOQ74014-add.nxs")
42+
sample = ws.sample()
43+
self.assertEqual(3, sample.getGeometryFlag())
44+
self.assertEqual(10.0, sample.getHeight())
45+
self.assertEqual(10.0, sample.getWidth())
46+
self.assertEqual(1.0, sample.getThickness())
47+
48+
def test_isis_nexus_get_sample_info_using_file_information(self):
49+
with patch("SANS.SANSadd2.get_geometry_information_isis_nexus") as mocked_get_geo_info:
50+
mocked_get_geo_info.return_value = (8.0, 8.0, 2.0, SampleShape.DISC)
51+
SANSadd2.add_runs(("74014", "74014"), "LOQ", ".nxs", rawTypes=(".add", ".raw", ".s*"), lowMem=False)
52+
self.assertEqual(1, mocked_get_geo_info.call_count)

0 commit comments

Comments
 (0)