diff --git a/docs/user-guide/dream/dream-instrument-view.ipynb b/docs/user-guide/dream/dream-instrument-view.ipynb index 1c69fa7e..3a3765a2 100644 --- a/docs/user-guide/dream/dream-instrument-view.ipynb +++ b/docs/user-guide/dream/dream-instrument-view.ipynb @@ -44,7 +44,7 @@ "outputs": [], "source": [ "dg = dream.io.load_geant4_csv(\n", - " dream.data.get_path('data_dream_with_sectors.csv.zip')\n", + " dream.data.get_path('data_dream0_new_hkl_Si_pwd.csv.zip')\n", ")\n", "dg = dg['instrument'] # Extract the instrument data\n", "\n", diff --git a/src/ess/dream/data.py b/src/ess/dream/data.py index 2a4f5e27..fe1b694d 100644 --- a/src/ess/dream/data.py +++ b/src/ess/dream/data.py @@ -19,6 +19,7 @@ def _make_pooch(): version=_version, registry={ 'data_dream_with_sectors.csv.zip': 'md5:52ae6eb3705e5e54306a001bc0ae85d8', + 'data_dream0_new_hkl_Si_pwd.csv.zip': 'md5:d0ae518dc1b943bb817b3d18c354ed01', # noqa: E501 'DREAM_nexus_sorted-2023-12-07.nxs': 'md5:22824e14f6eb950d24a720b2a0e2cb66', 'DREAM_simple_pwd_workflow/data_dream_diamond_vana_container_sample_union.csv.zip': 'md5:33302d0506b36aab74003b8aed4664cc', # noqa: E501 'DREAM_simple_pwd_workflow/data_dream_diamond_vana_container_sample_union_run2.csv.zip': 'md5:c7758682f978d162dcb91e47c79abb83', # noqa: E501 diff --git a/src/ess/dream/io/geant4.py b/src/ess/dream/io/geant4.py index 6a671697..eb602a2c 100644 --- a/src/ess/dream/io/geant4.py +++ b/src/ess/dream/io/geant4.py @@ -19,6 +19,7 @@ MANTLE_DETECTOR_ID = sc.index(7) HIGH_RES_DETECTOR_ID = sc.index(8) +SANS_DETECTOR_ID = sc.index(9) ENDCAPS_DETECTOR_IDS = tuple(map(sc.index, (3, 4, 5, 6))) @@ -95,8 +96,8 @@ def _group(detectors: Dict[str, sc.DataArray]) -> Dict[str, sc.DataGroup]: elements = ('module', 'segment', 'counter', 'wire', 'strip') def group(key: str, da: sc.DataArray) -> sc.DataArray: - if key == 'high_resolution': - # Only the HR detector has sectors. + if key in ['high_resolution', 'sans']: + # Only the HR and SANS detectors have sectors. return da.group('sector', *elements) res = da.group(*elements) res.bins.coords.pop('sector', None) @@ -110,7 +111,12 @@ def _split_detectors( ) -> Dict[str, sc.DataArray]: groups = data.group( sc.concat( - [MANTLE_DETECTOR_ID, HIGH_RES_DETECTOR_ID, *ENDCAPS_DETECTOR_IDS], + [ + MANTLE_DETECTOR_ID, + HIGH_RES_DETECTOR_ID, + SANS_DETECTOR_ID, + *ENDCAPS_DETECTOR_IDS, + ], dim=detector_id_name, ) ) @@ -123,6 +129,10 @@ def _split_detectors( high_res := _extract_detector(groups, detector_id_name, HIGH_RES_DETECTOR_ID) ) is not None: detectors['high_resolution'] = high_res.copy() + if ( + sans := _extract_detector(groups, detector_id_name, SANS_DETECTOR_ID) + ) is not None: + detectors['sans'] = sans.copy() endcaps_list = [ det diff --git a/tests/dream/io/geant4_test.py b/tests/dream/io/geant4_test.py index db216eb6..5c082f80 100644 --- a/tests/dream/io/geant4_test.py +++ b/tests/dream/io/geant4_test.py @@ -16,6 +16,11 @@ @pytest.fixture(scope='module') def file_path(): + return data.get_path('data_dream0_new_hkl_Si_pwd.csv.zip') + + +@pytest.fixture(scope='module') +def file_path_without_sans(): return data.get_path('data_dream_with_sectors.csv.zip') @@ -26,11 +31,23 @@ def load_file(file_path): return archive.read(archive.namelist()[0]) +# Load file into memory only once +@pytest.fixture(scope='module') +def load_file_without_sans(file_path_without_sans): + with zipfile.ZipFile(file_path_without_sans, 'r') as archive: + return archive.read(archive.namelist()[0]) + + @pytest.fixture() def file(load_file): return BytesIO(load_file) +@pytest.fixture() +def file_without_sans(load_file_without_sans): + return BytesIO(load_file_without_sans) + + def assert_index_coord( coord: sc.Variable, *, values: Optional[Set[int]] = None ) -> None: @@ -46,6 +63,22 @@ def test_load_geant4_csv_loads_expected_structure(file): assert isinstance(loaded, sc.DataGroup) assert loaded.keys() == {'instrument'} + instrument = loaded['instrument'] + assert isinstance(instrument, sc.DataGroup) + assert instrument.keys() == { + 'mantle', + 'high_resolution', + 'sans', + 'endcap_forward', + 'endcap_backward', + } + + +def test_load_geant4_csv_loads_expected_structure_without_sans(file_without_sans): + loaded = load_geant4_csv(file_without_sans) + assert isinstance(loaded, sc.DataGroup) + assert loaded.keys() == {'instrument'} + instrument = loaded['instrument'] assert isinstance(instrument, sc.DataGroup) assert instrument.keys() == { @@ -127,6 +160,23 @@ def test_load_geant4_csv_high_resolution_has_expected_coords(file): assert 'position' in hr.bins.coords +def test_load_geant4_csv_sans_has_expected_coords(file): + sans = load_geant4_csv(file)['instrument']['sans']['events'] + assert_index_coord(sans.coords['module']) + assert_index_coord(sans.coords['segment']) + assert_index_coord(sans.coords['counter']) + + # check ranges only if csv file contains events from SANS detectors + if len(sans.coords['module'].values) > 0: + assert_index_coord(sans.coords['wire'], values=set(range(1, 17))) + assert_index_coord(sans.coords['strip'], values=set(range(1, 33))) + assert_index_coord(sans.coords['sector'], values=set(range(1, 5))) + + assert 'tof' in sans.bins.coords + assert 'wavelength' in sans.bins.coords + assert 'position' in sans.bins.coords + + def test_geant4_in_pipeline(file_path, file): from ess.dream.io.geant4 import providers