From 7e67eff5eff82e83b633c472e4ed5171df4f616b Mon Sep 17 00:00:00 2001 From: YooSunYoung <17974113+YooSunYoung@users.noreply.github.com> Date: Fri, 24 Jul 2026 15:32:21 +0200 Subject: [PATCH 1/2] Update mcstas to nexus notebook. --- packages/essimaging/src/ess/odin/__init__.py | 3 +- packages/essimaging/src/ess/odin/data.py | 10 ++--- .../tests/odin/data_reduction_test.py | 8 ++-- .../essimaging/tools/mcstas_to_nexus.ipynb | 45 +++++++++++++------ 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/packages/essimaging/src/ess/odin/__init__.py b/packages/essimaging/src/ess/odin/__init__.py index 28d0831ba..7d315a5d7 100644 --- a/packages/essimaging/src/ess/odin/__init__.py +++ b/packages/essimaging/src/ess/odin/__init__.py @@ -3,7 +3,7 @@ import importlib.metadata -from . import beamline +from . import beamline, data from .workflows import OdinBraggEdgeWorkflow, OdinOrcaWorkflow, OdinWorkflow try: @@ -18,4 +18,5 @@ "OdinOrcaWorkflow", "OdinWorkflow", "beamline", + "data", ] diff --git a/packages/essimaging/src/ess/odin/data.py b/packages/essimaging/src/ess/odin/data.py index 4d980e903..e4ff0a80e 100644 --- a/packages/essimaging/src/ess/odin/data.py +++ b/packages/essimaging/src/ess/odin/data.py @@ -8,12 +8,12 @@ _registry = make_registry( 'ess/odin', - version="1", + version="2", files={ - "iron_simulation_ob_large.nxs": "md5:a93517ea2aa167d134ca63671f663f99", - "iron_simulation_ob_small.nxs": "md5:7591ed8f0adec2658fb08190bd530b12", - "iron_simulation_sample_large.nxs": "md5:c162b6abeccb51984880d8d5002bae95", - "iron_simulation_sample_small.nxs": "md5:dda6fb30aa88780c5a3d4cef6ea05278", + "iron_simulation_sample_small.nxs": "md5:80c761ae23afac36385d96db186714b5", + "iron_simulation_ob_small.nxs": "md5:0510ec416526169cea1c1a2d96e32877", + "iron_simulation_sample_large.nxs": "md5:df22835fae4d1e4a3707ce2ee52eaf1d", + "iron_simulation_ob_large.nxs": "md5:a3b3d9b75dd2edada0be0d17ee29b905", "ODIN-wavelength-lookup-table-5m-65m.h5": "md5:44eef2a2e826cec688aeb1b985eb9f9e", # noqa: E501 "ymir_lego_odin.hdf": "md5:8e8708891e2574046b6f372e5e3516a5", }, diff --git a/packages/essimaging/tests/odin/data_reduction_test.py b/packages/essimaging/tests/odin/data_reduction_test.py index 96aba1cb4..306b5d88b 100644 --- a/packages/essimaging/tests/odin/data_reduction_test.py +++ b/packages/essimaging/tests/odin/data_reduction_test.py @@ -85,7 +85,7 @@ def test_can_compute_tof(run_type, wavelength_mode): def test_publish_reduced_scitiff(output_folder: Path): wf = _make_workflow("analytical") wf[MaskingRules] = {} - new_sizes = {'dim_0': 64, 'dim_1': 64} + new_sizes = {'x_pixel_offset': 64, 'y_pixel_offset': 64} tbins = sc.linspace('tof', 1.3e4, 1.5e5, 257, unit='us') sample = wf.compute(TofDetector[SampleRun]).drop_coords('detector_number') @@ -98,9 +98,9 @@ def test_publish_reduced_scitiff(output_folder: Path): normed = num / den - to_scitiff = normed.rename_dims(dim_0='y', dim_1='x', tof='t').drop_coords( - 'position' - ) + to_scitiff = normed.rename_dims( + y_pixel_offset='y', x_pixel_offset='x', tof='t' + ).drop_coords('position') assert "tof" in to_scitiff.coords assert "Ltotal" in to_scitiff.coords diff --git a/packages/essimaging/tools/mcstas_to_nexus.ipynb b/packages/essimaging/tools/mcstas_to_nexus.ipynb index 44ddf0b27..f31c15930 100644 --- a/packages/essimaging/tools/mcstas_to_nexus.ipynb +++ b/packages/essimaging/tools/mcstas_to_nexus.ipynb @@ -133,11 +133,13 @@ " \"\"\"\n", " # Find shape of detector panel\n", " with h5.File(template_nexus_file, \"r\") as f:\n", - " shape = f[f\"{detector_entry_path}/x_pixel_offset\"].shape\n", + " x_shape = f[f\"{detector_entry_path}/x_pixel_offset\"].shape[0]\n", + " y_shape = f[f\"{detector_entry_path}/y_pixel_offset\"].shape[0]\n", " det_numbers = f[f\"{detector_entry_path}/detector_number\"][()]\n", "\n", " da = load_mcstas_simulation_data(mcstas_data_file, nevents=int(nevents))\n", - " binned = da.bin(y=shape[0], x=shape[1]).rename_dims(y=\"dim_0\", x=\"dim_1\")\n", + " binned = da.bin(y=y_shape, x=x_shape).rename_dims(y=\"dim_0\", x=\"dim_1\")\n", + " display(\"Binned data:\", binned)\n", "\n", " toa = binned.bins.coords[\"time_of_arrival\"].bins.concat().value\n", "\n", @@ -173,9 +175,10 @@ "\n", " # Now edit the template file\n", " print(f\"Writing {outfile} file\")\n", - " shutil.copyfile(template_nexus_file, outfile)\n", + " tmp_output = \"tmp.output.nxs\"\n", + " shutil.copyfile(template_nexus_file, tmp_output)\n", "\n", - " with h5.File(outfile, \"r+\") as f:\n", + " with h5.File(tmp_output, \"r+\") as f:\n", "\n", " # Detector data\n", " if detector_entry_path is not None:\n", @@ -222,7 +225,18 @@ " values=event_index.coords[\"event_time_zero\"]\n", " .to(unit=monitor_data[\"event_time_zero\"].attrs[\"units\"], copy=False)\n", " .values.astype(int),\n", - " )" + " )\n", + "\n", + " # Remove user info\n", + " for subgroup in f['entry']:\n", + " if f[f'entry/{subgroup}'].attrs.get('NX_class') == 'NXuser':\n", + " del f[f'entry/{subgroup}']\n", + "\n", + " with h5.File(tmp_output, \"r\") as f:\n", + " with h5.File(outfile, \"w\") as outf:\n", + " for key in f:\n", + " outf.copy(f[key], key)\n", + " outf.attrs.update(f.attrs)" ] }, { @@ -232,20 +246,23 @@ "metadata": {}, "outputs": [], "source": [ + "directory_path = \"/dmsc/scipp/odin/\"\n", "files = [\n", - " \"small_mcstas_sample_images.h5\",\n", - " \"small_mcstas_ob_images.h5\",\n", " \"iron_simulation_sample.h5\",\n", " \"iron_simulation_ob.h5\",\n", "]\n", "\n", + "suffixes = {'_small.nxs': 1e6, '_large.nxs': 1e7, '_extra_large.nxs': 1e8}\n", + "\n", "for file in files:\n", - " mcstas_to_nexus(\n", - " mcstas_data_file=file,\n", - " template_nexus_file=\"977695_00072982.hdf\",\n", - " outfile=file.replace(\".h5\", \".nxs\"),\n", - " nevents=1e6,\n", - " )" + " for suffix, nevents in suffixes.items():\n", + " mcstas_to_nexus(\n", + " mcstas_data_file=directory_path+\"/\"+file,\n", + " template_nexus_file=\"/ess/raw/coda/999999/raw/coda_odin_999999_00013934.hdf\",\n", + " monitor_entry_path=None,\n", + " outfile=file.replace(\".h5\", suffix),\n", + " nevents=nevents,\n", + " )" ] } ], @@ -265,7 +282,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.7" + "version": "3.11.15" } }, "nbformat": 4, From 399489a77b14c99699391496d180940388f903c8 Mon Sep 17 00:00:00 2001 From: YooSunYoung <17974113+YooSunYoung@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:33:19 +0200 Subject: [PATCH 2/2] Histogram with lower resolution for docs build. --- .../docs/odin/odin-data-reduction.ipynb | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/essimaging/docs/odin/odin-data-reduction.ipynb b/packages/essimaging/docs/odin/odin-data-reduction.ipynb index 595acd925..5397d372e 100644 --- a/packages/essimaging/docs/odin/odin-data-reduction.ipynb +++ b/packages/essimaging/docs/odin/odin-data-reduction.ipynb @@ -207,13 +207,25 @@ "metadata": {}, "outputs": [], "source": [ - "sample_wavs.hist().plot(aspect='equal')" + "# ODIN timepix has 4096x4096 pixels by default, which is too many to visualize without `ignore_size=True` option.\n", + "# we will use 256x256 pixels instead for visualization in the documentation.\n", + "vis_resolution = {\"x_pixel_offset\": 256, \"y_pixel_offset\": 256}" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "id": "19", "metadata": {}, + "outputs": [], + "source": [ + "sample_wavs.hist(vis_resolution).plot(aspect='equal')" + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, "source": [ "The brighter areas around the edges are regions where neutrons did not travel through the sample.\n", "We thus want to mask those out using masking rules based on the spatial coordinates of the data:" @@ -222,7 +234,7 @@ { "cell_type": "code", "execution_count": null, - "id": "20", + "id": "21", "metadata": {}, "outputs": [], "source": [ @@ -235,18 +247,18 @@ { "cell_type": "code", "execution_count": null, - "id": "21", + "id": "22", "metadata": {}, "outputs": [], "source": [ "masked = wf.compute(CorrectedDetector[SampleRun])\n", "\n", - "masked.hist().plot(aspect='equal')" + "masked.hist(vis_resolution).plot(aspect='equal')" ] }, { "cell_type": "markdown", - "id": "22", + "id": "23", "metadata": {}, "source": [ "## Normalize to open beam\n", @@ -258,7 +270,7 @@ { "cell_type": "code", "execution_count": null, - "id": "23", + "id": "24", "metadata": {}, "outputs": [], "source": [ @@ -274,7 +286,7 @@ }, { "cell_type": "markdown", - "id": "24", + "id": "25", "metadata": {}, "source": [ "## Save the final result" @@ -283,7 +295,7 @@ { "cell_type": "code", "execution_count": null, - "id": "25", + "id": "26", "metadata": {}, "outputs": [], "source": [ @@ -312,7 +324,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.7" + "version": "3.11.15" } }, "nbformat": 4,