diff --git a/docs/user-guide/dream/dream-simulation-si-wfm.ipynb b/docs/user-guide/dream/dream-simulation-si-wfm.ipynb new file mode 100644 index 00000000..9c7240ca --- /dev/null +++ b/docs/user-guide/dream/dream-simulation-si-wfm.ipynb @@ -0,0 +1,677 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "# DREAM: simulation with Si powder sample\n", + "\n", + "This notebook illustrates the reduction of Powder Diffraction data for DREAM.\n", + "\n", + "- It uses simulated data from McStas/GEANT4 in the High-Flux configuration\n", + "- The samples were Si powder and Vanadium (for normalisation)\n", + "\n", + "For Vanadium, we use the result of a McStas/GEANT4 simulation using the `Incoherent` component to model the Vanadium sample. \n", + "\n", + "In this notebook the input files are NeXus files.\n", + "They created using one of the NeXus files from the CODA pipeline and stored in Scicat and by adding simulated data from McStas/GEANT4." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import scipp as sc\n", + "import scippneutron as scn\n", + "import plopp as pp\n", + "from ess.dream import data as dream_data\n", + "import scippnexus as snx" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "def _nonfinite_to_zero(\n", + " data: sc.DataGroup | sc.DataArray | sc.Dataset,\n", + ") -> sc.DataGroup | sc.DataArray | sc.Dataset:\n", + " \"\"\"\n", + " Replace NaN, positive and negative infs by zero\n", + " \"\"\"\n", + " if data.variances is not None:\n", + " replacement = sc.scalar(0.0, variance=0.0, unit=data.unit)\n", + " else:\n", + " replacement = sc.scalar(0.0, unit=data.unit)\n", + " return sc.nan_to_num(data, nan=replacement, posinf=replacement, neginf=replacement)\n", + "\n", + "\n", + "def clean_all_dets(\n", + " data: sc.DataGroup | sc.DataArray | sc.Dataset,\n", + ") -> sc.DataGroup | sc.DataArray | sc.Dataset:\n", + " \"\"\"Clean the data, removing NaNs.\"\"\"\n", + " dg_out = sc.DataGroup()\n", + " for item in data.keys():\n", + " out = data[item].copy()\n", + " out.data = _nonfinite_to_zero(out.data)\n", + " dg_out[item] = out\n", + " return dg_out\n", + "\n", + "\n", + "def load_dream_nxs(filename: str) -> sc.DataGroup:\n", + " \"\"\" \"\"\"\n", + " dg_out = sc.DataGroup()\n", + " pattern = \"_detector\"\n", + " period = (1.0 / sc.scalar(14.0, unit=\"Hz\")).to(unit=\"ns\")\n", + "\n", + " # temporarily hard-coding values of sample, source and cave monitor positions\n", + " # until bug fix for DREAM NeXus file\n", + " source_position = sc.vector(value=np.array([-3.478, 0.0, -76550]), unit=\"mm\")\n", + " sample_position = sc.vector(value=np.array([0.0, 0.0, 0.0]), unit=\"mm\")\n", + "\n", + " with snx.File(filename) as f:\n", + " inst = f[\"entry\"][\"instrument\"]\n", + " for key in inst:\n", + " if key.endswith(pattern):\n", + " name = key.removesuffix(pattern)\n", + " dg = inst[key][()]\n", + " da = dg[f\"{name}_event_data\"]\n", + " # dg_out[name]['event'].variances = dg_out[name]['event'].values\n", + "\n", + " # add position\n", + " da.coords[\"position\"] = sc.spatial.as_vectors(\n", + " da.coords[\"x_pixel_offset\"],\n", + " da.coords[\"y_pixel_offset\"],\n", + " da.coords[\"z_pixel_offset\"],\n", + " )\n", + "\n", + " # add sample and source position\n", + " da.coords[\"source_position\"] = source_position\n", + " da.coords[\"sample_position\"] = sample_position\n", + "\n", + " # rename ToF\n", + " da.bins.coords[\"tof\"] = da.bins.coords.pop(\"event_time_offset\")\n", + "\n", + " # add variances\n", + " da.bins.constituents[\"data\"].variances = da.bins.constituents[\n", + " \"data\"\n", + " ].values\n", + "\n", + " # In the raw data, the tofs extend beyond 71ms.\n", + " # This is thus not an event_time_offset.\n", + " # In addition, there is only one event_time_zero for all events,\n", + " # when there should be at least 2 because some tofs are larger than 71ms\n", + "\n", + " # Bin the data into bins with a 71ms period\n", + " da = da.bin(tof=sc.arange(\"tof\", 3) * period)\n", + " # Add a event_time_zero coord for each bin, but not as bin edges, as all events in the same pulse have the same event_time_zero, hence the `[:2]`\n", + " da.coords[\"event_time_zero\"] = (\n", + " sc.scalar(1730450434078980000, unit=\"ns\") + da.coords[\"tof\"]\n", + " )[:2]\n", + " # Remove the meaningless tof coord at the top level\n", + " del da.coords[\"tof\"]\n", + " # Remove the original (wrong) event_time_zero event coord inside the bins and rename the dim\n", + " del da.bins.coords[\"event_time_zero\"]\n", + " da = da.rename_dims(tof=\"event_time_zero\")\n", + " # Compute a proper event_time_offset as tof % period\n", + " da.bins.coords[\"event_time_offset\"] = (\n", + " da.bins.coords.pop(\"tof\") % period\n", + " ).to(unit=\"us\")\n", + " dg_out[name] = da\n", + "\n", + " return dg_out\n", + "\n", + "\n", + "def load_monitor(file: str) -> sc.DataArray:\n", + " \"\"\"\n", + " Load histogrammed monitor data,\n", + " making sure that the time-of-flight wraps around the pulse period.\n", + " \"\"\"\n", + " tof, tof_count = np.loadtxt(file, usecols=(0, 1), skiprows=42, unpack=True)\n", + "\n", + " raw_data = sc.DataArray(\n", + " data=sc.array(dims=[\"tof\"], values=tof_count, unit=\"counts\"),\n", + " coords={\"tof\": sc.array(dims=[\"tof\"], values=tof * 1000, unit=\"ns\")},\n", + " )\n", + " raw_data = raw_data[\"tof\", 0.0 * sc.Unit(\"ns\") : 1e8 * sc.Unit(\"ns\")].copy()\n", + "\n", + " # Convert coord to bin edges\n", + " tof = raw_data.coords[\"tof\"]\n", + " center = sc.midpoints(tof, dim=\"tof\")\n", + " left = center[\"tof\", 0:1] - (tof[\"tof\", 1] - tof[\"tof\", 0])\n", + " right = center[\"tof\", -1] + (tof[\"tof\", -1] - tof[\"tof\", -2])\n", + " raw_data.coords[\"tof\"] = sc.concat([left, center, right], \"tof\")\n", + "\n", + " period = (1.0 / sc.scalar(14.0, unit=\"Hz\")).to(unit=raw_data.coords[\"tof\"].unit)\n", + " bins = sc.sort(sc.concat([raw_data.coords[\"tof\"], period], \"tof\"), \"tof\")\n", + " raw_data = raw_data.rebin(tof=bins)\n", + " part1 = raw_data[\"tof\", :period].copy()\n", + " part2 = raw_data[\"tof\", period:].copy()\n", + " part2.coords[\"tof\"] = part2.coords[\"tof\"] % period\n", + " bins = sc.linspace(\"tof\", 0, period.value, 513, unit=period.unit)\n", + "\n", + " out = part2.rebin(tof=bins) + part1.rebin(tof=bins)\n", + " out = out.rename(tof=\"time_of_flight\")\n", + "\n", + " out.coords[\"Ltotal\"] = sc.scalar(np.sqrt(3.478**2 + 72330**2), unit=\"mm\")\n", + " return out" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "## Beamline properties\n", + "\n", + "We set up the chopper parameters,\n", + "used to determine the frame boundaries and compute an accurate neutron time-of-flight." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "import sciline as sl\n", + "from scippneutron.chopper import DiskChopper\n", + "from scippneutron.tof import unwrap\n", + "from scippneutron.tof import chopper_cascade\n", + "\n", + "psc1 = DiskChopper(\n", + " frequency=sc.scalar(14.0, unit=\"Hz\"),\n", + " beam_position=sc.scalar(0.0, unit=\"deg\"),\n", + " phase=sc.scalar(286 - 180, unit=\"deg\"),\n", + " axle_position=sc.vector(value=[0, 0, 6.145], unit=\"m\"),\n", + " slit_begin=sc.array(\n", + " dims=[\"cutout\"],\n", + " values=[-1.23, 70.49, 84.765, 113.565, 170.29, 271.635, 286.035, 301.17],\n", + " unit=\"deg\",\n", + " ),\n", + " slit_end=sc.array(\n", + " dims=[\"cutout\"],\n", + " values=[1.23, 73.51, 88.035, 116.835, 175.31, 275.565, 289.965, 303.63],\n", + " unit=\"deg\",\n", + " ),\n", + " slit_height=sc.scalar(10.0, unit=\"cm\"),\n", + " radius=sc.scalar(30.0, unit=\"cm\"),\n", + ")\n", + "\n", + "psc2 = DiskChopper(\n", + " frequency=sc.scalar(-14.0, unit=\"Hz\"),\n", + " beam_position=sc.scalar(0.0, unit=\"deg\"),\n", + " phase=sc.scalar(-236, unit=\"deg\"),\n", + " axle_position=sc.vector(value=[0, 0, 6.155], unit=\"m\"),\n", + " slit_begin=sc.array(\n", + " dims=[\"cutout\"],\n", + " values=[-1.23, 27.0, 55.8, 142.385, 156.765, 214.115, 257.23, 315.49],\n", + " unit=\"deg\",\n", + " ),\n", + " slit_end=sc.array(\n", + " dims=[\"cutout\"],\n", + " values=[1.23, 30.6, 59.4, 145.615, 160.035, 217.885, 261.17, 318.11],\n", + " unit=\"deg\",\n", + " ),\n", + " slit_height=sc.scalar(10.0, unit=\"cm\"),\n", + " radius=sc.scalar(30.0, unit=\"cm\"),\n", + ")\n", + "\n", + "oc = DiskChopper(\n", + " frequency=sc.scalar(14.0, unit=\"Hz\"),\n", + " beam_position=sc.scalar(0.0, unit=\"deg\"),\n", + " phase=sc.scalar(297 - 180 - 90, unit=\"deg\"),\n", + " axle_position=sc.vector(value=[0, 0, 6.174], unit=\"m\"),\n", + " slit_begin=sc.array(dims=[\"cutout\"], values=[-27.6 * 0.5], unit=\"deg\"),\n", + " slit_end=sc.array(dims=[\"cutout\"], values=[27.6 * 0.5], unit=\"deg\"),\n", + " slit_height=sc.scalar(10.0, unit=\"cm\"),\n", + " radius=sc.scalar(30.0, unit=\"cm\"),\n", + ")\n", + "\n", + "bcc = DiskChopper(\n", + " frequency=sc.scalar(112.0, unit=\"Hz\"),\n", + " beam_position=sc.scalar(0.0, unit=\"deg\"),\n", + " phase=sc.scalar(240 - 180, unit=\"deg\"),\n", + " axle_position=sc.vector(value=[0, 0, 9.78], unit=\"m\"),\n", + " slit_begin=sc.array(dims=[\"cutout\"], values=[-36.875, 143.125], unit=\"deg\"),\n", + " slit_end=sc.array(dims=[\"cutout\"], values=[36.875, 216.875], unit=\"deg\"),\n", + " slit_height=sc.scalar(10.0, unit=\"cm\"),\n", + " radius=sc.scalar(30.0, unit=\"cm\"),\n", + ")\n", + "\n", + "t0 = DiskChopper(\n", + " frequency=sc.scalar(28.0, unit=\"Hz\"),\n", + " beam_position=sc.scalar(0.0, unit=\"deg\"),\n", + " phase=sc.scalar(280 - 180, unit=\"deg\"),\n", + " axle_position=sc.vector(value=[0, 0, 13.05], unit=\"m\"),\n", + " slit_begin=sc.array(dims=[\"cutout\"], values=[-314.9 * 0.5], unit=\"deg\"),\n", + " slit_end=sc.array(dims=[\"cutout\"], values=[314.9 * 0.5], unit=\"deg\"),\n", + " slit_height=sc.scalar(10.0, unit=\"cm\"),\n", + " radius=sc.scalar(30.0, unit=\"cm\"),\n", + ")\n", + "\n", + "disk_choppers = {\"psc1\": psc1, \"psc2\": psc2, \"oc\": oc, \"bcc\": bcc, \"t0\": t0}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "choppers = {\n", + " key: chopper_cascade.Chopper.from_disk_chopper(\n", + " chop,\n", + " pulse_frequency=sc.scalar(14.0, unit=\"Hz\"),\n", + " npulses=1,\n", + " )\n", + " for key, chop in disk_choppers.items()\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "pulse_tmin = sc.scalar(0.0, unit=\"ms\")\n", + "pulse_tmax = sc.scalar(5.0, unit=\"ms\")\n", + "pulse_wmin = sc.scalar(0.2, unit=\"angstrom\")\n", + "pulse_wmax = sc.scalar(20.0, unit=\"angstrom\")\n", + "\n", + "frames = chopper_cascade.FrameSequence.from_source_pulse(\n", + " time_min=pulse_tmin,\n", + " time_max=pulse_tmax,\n", + " wavelength_min=pulse_wmin,\n", + " wavelength_max=pulse_wmax,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "# Chop the frames\n", + "chopped = frames.chop(choppers.values())\n", + "\n", + "# Propagate the neutrons to the detector\n", + "at_detector = chopped.propagate_to(sc.scalar(76.5, unit=\"m\"))\n", + "\n", + "# Visualize the results\n", + "cascade_fig, cascade_ax = at_detector.draw()" + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Load and process monitor data\n", + "\n", + "For normalisation, we consider the Cave monitor contained in McStas model of DREAM.\n", + "We load the monitors from the Si and Vanadium simulations.\n", + "\n", + "\n", + "
\n", + "\n", + "*NOTE:*\n", + "\n", + "We use the ASCII file from McStas. This is a temporary solution, which will be replaced once monitor data have been added to the NeXus file.\n", + "\n", + "
\n", + "\n", + "### Load raw data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "tof_mon_cave_si = load_monitor(dream_data.stap_demo_2024_si_monitor())\n", + "tof_mon_cave_van = load_monitor(dream_data.stap_demo_2024_vanadium_monitor())\n", + "\n", + "tof_mon_cave_si.plot(grid=True, title=\"Si Cave tof monitor\") + tof_mon_cave_van.plot(\n", + " grid=True, title=\"Vana Cave tof monitor\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "10", + "metadata": {}, + "source": [ + "### Convert monitor data to wavelength" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "# Setup workflow\n", + "pl = sl.Pipeline(\n", + " (*unwrap.providers(), unwrap.re_histogram_tof_data), params=unwrap.params()\n", + ")\n", + "pl[unwrap.PulsePeriod] = 1.0 / sc.scalar(14.0, unit=\"Hz\")\n", + "\n", + "pl[unwrap.SourceTimeRange] = pulse_tmin, pulse_tmax\n", + "pl[unwrap.SourceWavelengthRange] = pulse_wmin, pulse_wmax\n", + "pl[unwrap.Choppers] = choppers\n", + "\n", + "# Si sample\n", + "pl[unwrap.RawData] = tof_mon_cave_si\n", + "pl[unwrap.Ltotal] = tof_mon_cave_si.coords[\"Ltotal\"]\n", + "tofs_si = pl.compute(unwrap.ReHistogrammedTofData)\n", + "\n", + "# Vanadium sample\n", + "pl[unwrap.RawData] = tof_mon_cave_van\n", + "pl[unwrap.Ltotal] = tof_mon_cave_van.coords[\"Ltotal\"]\n", + "tofs_van = pl.compute(unwrap.ReHistogrammedTofData)\n", + "\n", + "\n", + "# Convert to wavelength\n", + "wlgth_graph_monitor = {\n", + " **scn.conversion.graph.beamline.beamline(scatter=False),\n", + " **scn.conversion.graph.tof.elastic_wavelength(\"tof\"),\n", + "}\n", + "\n", + "mon_cave_si_wlgth = tofs_si.transform_coords(\"wavelength\", graph=wlgth_graph_monitor)\n", + "mon_cave_van_wlgth = tofs_van.transform_coords(\"wavelength\", graph=wlgth_graph_monitor)\n", + "\n", + "# Plot\n", + "mon_cave_si_wlgth.plot(\n", + " title=\"Monitor for Si sample in wavelength\", grid=True\n", + ") + mon_cave_van_wlgth.plot(\n", + " title=\"Monitor for Vanadium sample in wavelength\", grid=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "## Load and process detector data\n", + "\n", + "### Load raw data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "from ess.dream import data as dream_data\n", + "\n", + "sample = load_dream_nxs(dream_data.stap_demo_2024_si_sample())\n", + "vana = load_dream_nxs(dream_data.stap_demo_2024_vanadium_sample())\n", + "\n", + "sample" + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": {}, + "source": [ + "### Conversion to wavelength" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "detector_graph = {\n", + " **scn.conversion.graph.beamline.beamline(scatter=True),\n", + " **scn.conversion.graph.tof.elastic_wavelength(\"tof\"),\n", + "}\n", + "\n", + "dg_si_wlgth = sc.DataGroup()\n", + "dg_van_wlgth = sc.DataGroup()\n", + "\n", + "for run, out in ((sample, dg_si_wlgth), (vana, dg_van_wlgth)):\n", + " for key, val in run.items():\n", + " da = val.transform_coords([\"Ltotal\"], graph=detector_graph)\n", + " pl[unwrap.RawData] = da\n", + " pl[unwrap.Ltotal] = da.coords[\"Ltotal\"]\n", + "\n", + " result = pl.compute(unwrap.TofData)\n", + " out[key] = result.transform_coords(\"wavelength\", graph=detector_graph)" + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "## Normalize by integrated monitor counts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: we multiplied the sums by the bin width in the original notebook\n", + "\n", + "dg_si_wlgth_norm = dg_si_wlgth / mon_cave_si_wlgth.sum().data\n", + "dg_van_wlgth_norm = dg_van_wlgth / mon_cave_van_wlgth.sum().data" + ] + }, + { + "cell_type": "markdown", + "id": "18", + "metadata": {}, + "source": [ + "## Convert to d-spacing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19", + "metadata": {}, + "outputs": [], + "source": [ + "dspacing_graph = {\n", + " **scn.conversion.graph.beamline.beamline(scatter=True),\n", + " **scn.conversion.graph.tof.elastic_dspacing(\"tof\"),\n", + "}\n", + "\n", + "dg_si_dsp = dg_si_wlgth_norm.transform_coords(\n", + " [\"dspacing\", \"two_theta\"], graph=dspacing_graph\n", + ")\n", + "dg_van_dsp = dg_van_wlgth_norm.transform_coords(\n", + " [\"dspacing\", \"two_theta\"], graph=dspacing_graph\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, + "source": [ + "## Binning in d-spacing and two-theta\n", + "\n", + "We consider only the high-resolution and endcap backward detector banks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21", + "metadata": {}, + "outputs": [], + "source": [ + "ttheta_bin_edges_per_bank = {}\n", + "si_norm_bin = sc.DataGroup()\n", + "van_norm_bin = sc.DataGroup()\n", + "\n", + "dspacing_bins = sc.linspace(\"dspacing\", 0.55, 1.75, 601, unit=\"angstrom\")\n", + "\n", + "for bank in [\"endcap_backward\", \"high_resolution\"]:\n", + "\n", + " ttheta_bin_edges_per_bank[bank] = (\n", + " dg_si_dsp[bank].coords[\"two_theta\"].min().value,\n", + " dg_si_dsp[bank].coords[\"two_theta\"].max().value,\n", + " )\n", + "\n", + " twotheta_bins = sc.linspace(\n", + " \"two_theta\",\n", + " ttheta_bin_edges_per_bank[bank][0],\n", + " ttheta_bin_edges_per_bank[bank][1],\n", + " 181,\n", + " unit=\"rad\",\n", + " )\n", + "\n", + " si_norm_bin[bank] = dg_si_dsp[bank].bin(\n", + " two_theta=twotheta_bins, dspacing=dspacing_bins\n", + " )\n", + " van_norm_bin[bank] = dg_van_dsp[bank].bin(\n", + " two_theta=twotheta_bins, dspacing=dspacing_bins\n", + " )\n", + "\n", + "si_norm_bin" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22", + "metadata": {}, + "outputs": [], + "source": [ + "p_hr = pp.plot(\n", + " si_norm_bin[\"high_resolution\"].bins.concat(\"event_time_zero\").hist(),\n", + " norm=\"log\",\n", + " title=\"high_resolution\",\n", + ")\n", + "p_ebwd = pp.plot(\n", + " si_norm_bin[\"endcap_backward\"].bins.concat(\"event_time_zero\").hist(),\n", + " norm=\"log\",\n", + " title=\"endcap_backward\",\n", + ")\n", + "\n", + "p_hr / p_ebwd" + ] + }, + { + "cell_type": "markdown", + "id": "23", + "metadata": {}, + "source": [ + "## Normalize Si sample data by Vanadium" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24", + "metadata": {}, + "outputs": [], + "source": [ + "si_final_norm = si_norm_bin.hist() / van_norm_bin.hist()\n", + "cleaned_final_si = clean_all_dets(si_final_norm).sum(\"event_time_zero\")\n", + "cleaned_final_si" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "25", + "metadata": {}, + "outputs": [], + "source": [ + "fig = cleaned_final_si.sum(\"two_theta\").plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26", + "metadata": {}, + "outputs": [], + "source": [ + "theory = np.array(\n", + " [\n", + " 3.1353, 1.6374, 1.5677, 1.3576, 1.2458, 1.0451, 0.9600, 0.9179, 0.8281,\n", + " 0.8187, 0.7838, 0.7604, 0.7257, 0.7070, 0.6788, 0.6634, 0.6271, 0.6229,\n", + " 0.6072, 0.5961, 0.5693, 0.5543, 0.5458, 0.5250, 0.5226,\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27", + "metadata": {}, + "outputs": [], + "source": [ + "for line in theory:\n", + " fig.ax.axvline(line, color=\"gray\")\n", + "fig.canvas.draw()\n", + "fig.fig.set_size_inches((12.0, 4.0))\n", + "fig" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/requirements/base.txt b/requirements/base.txt index 153660af..e34e07ed 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,7 +5,7 @@ # # pip-compile-multi # -asttokens==2.4.1 +asttokens==3.0.0 # via stack-data click==8.1.7 # via dask @@ -19,7 +19,7 @@ cyclebane==24.10.0 # via sciline cycler==0.12.1 # via matplotlib -dask==2024.11.2 +dask==2024.12.0 # via -r base.in decorator==5.1.1 # via ipython @@ -29,7 +29,7 @@ exceptiongroup==1.2.2 # via ipython executing==2.1.0 # via stack-data -fonttools==4.55.0 +fonttools==4.55.3 # via matplotlib fsspec==2024.10.0 # via dask @@ -43,7 +43,7 @@ importlib-metadata==8.5.0 # via dask ipydatawidgets==4.3.5 # via pythreejs -ipython==8.29.0 +ipython==8.30.0 # via ipywidgets ipywidgets==8.1.5 # via @@ -57,7 +57,7 @@ kiwisolver==1.4.7 # via matplotlib locket==1.0.0 # via partd -matplotlib==3.9.2 +matplotlib==3.10.0 # via # mpltoolbox # plopp @@ -67,7 +67,7 @@ mpltoolbox==24.5.1 # via scippneutron networkx==3.4.2 # via cyclebane -numpy==2.1.3 +numpy==2.2.0 # via # -r base.in # contourpy @@ -123,7 +123,7 @@ scipp==24.11.2 # essreduce # scippneutron # scippnexus -scippneutron==24.11.0 +scippneutron==24.12.0 # via # -r base.in # essreduce @@ -136,10 +136,8 @@ scipy==1.14.1 # via # scippneutron # scippnexus -six==1.16.0 - # via - # asttokens - # python-dateutil +six==1.17.0 + # via python-dateutil stack-data==0.6.3 # via ipython toolz==1.0.0 diff --git a/requirements/basetest.txt b/requirements/basetest.txt index ad1f8e94..906d87e8 100644 --- a/requirements/basetest.txt +++ b/requirements/basetest.txt @@ -5,7 +5,7 @@ # # pip-compile-multi # -certifi==2024.8.30 +certifi==2024.12.14 # via requests charset-normalizer==3.4.0 # via requests @@ -15,7 +15,7 @@ idna==3.10 # via requests iniconfig==2.0.0 # via pytest -numpy==2.1.3 +numpy==2.2.0 # via pandas packaging==24.2 # via @@ -29,7 +29,7 @@ pluggy==1.5.0 # via pytest pooch==1.8.2 # via -r basetest.in -pytest==8.3.3 +pytest==8.3.4 # via -r basetest.in python-dateutil==2.9.0.post0 # via pandas @@ -37,7 +37,7 @@ pytz==2024.2 # via pandas requests==2.32.3 # via pooch -six==1.16.0 +six==1.17.0 # via python-dateutil tomli==2.2.1 # via pytest diff --git a/requirements/ci.txt b/requirements/ci.txt index 045acba6..c3ccdde1 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -7,7 +7,7 @@ # cachetools==5.5.0 # via tox -certifi==2024.8.30 +certifi==2024.12.14 # via requests chardet==5.2.0 # via tox diff --git a/requirements/dev.txt b/requirements/dev.txt index d7d5de02..d77a0233 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -14,7 +14,7 @@ -r wheels.txt annotated-types==0.7.0 # via pydantic -anyio==4.6.2.post1 +anyio==4.7.0 # via # httpx # jupyter-server @@ -40,7 +40,7 @@ h11==0.14.0 # via httpcore httpcore==1.0.7 # via httpx -httpx==0.27.2 +httpx==0.28.1 # via jupyterlab isoduration==20.11.0 # via jsonschema @@ -67,7 +67,7 @@ jupyter-server==2.14.2 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.3.1 +jupyterlab==4.3.3 # via -r dev.in jupyterlab-server==2.27.3 # via jupyterlab @@ -83,15 +83,15 @@ pip-tools==7.4.1 # via pip-compile-multi plumbum==1.9.0 # via copier -prometheus-client==0.21.0 +prometheus-client==0.21.1 # via jupyter-server pycparser==2.22 # via cffi -pydantic==2.10.2 +pydantic==2.10.3 # via copier pydantic-core==2.27.1 # via pydantic -python-json-logger==2.0.7 +python-json-logger==3.2.1 # via jupyter-events questionary==1.10.0 # via copier @@ -106,16 +106,14 @@ rfc3986-validator==0.1.1 send2trash==1.8.3 # via jupyter-server sniffio==1.3.1 - # via - # anyio - # httpx + # via anyio terminado==0.18.1 # via # jupyter-server # jupyter-server-terminals toposort==1.10 # via pip-compile-multi -types-python-dateutil==2.9.0.20241003 +types-python-dateutil==2.9.0.20241206 # via arrow uri-template==1.3.0 # via jsonschema diff --git a/requirements/docs.txt b/requirements/docs.txt index 4dc07134..316cdbc4 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -10,7 +10,7 @@ accessible-pygments==0.0.5 # via pydata-sphinx-theme alabaster==1.0.0 # via sphinx -attrs==24.2.0 +attrs==24.3.0 # via # jsonschema # referencing @@ -24,11 +24,11 @@ beautifulsoup4==4.12.3 # pydata-sphinx-theme bleach==6.2.0 # via nbconvert -certifi==2024.8.30 +certifi==2024.12.14 # via requests charset-normalizer==3.4.0 # via requests -debugpy==1.8.9 +debugpy==1.8.11 # via ipykernel defusedxml==0.7.1 # via nbconvert @@ -40,7 +40,7 @@ docutils==0.21.2 # pydata-sphinx-theme # sphinx # sphinxcontrib-bibtex -fastjsonschema==2.21.0 +fastjsonschema==2.21.1 # via nbformat idna==3.10 # via requests @@ -93,7 +93,7 @@ mistune==3.0.2 # via nbconvert myst-parser==4.0.0 # via -r docs.in -nbclient==0.10.0 +nbclient==0.10.1 # via nbconvert nbconvert==7.16.4 # via nbsphinx @@ -142,7 +142,7 @@ requests==2.32.3 # via # pooch # sphinx -rpds-py==0.21.0 +rpds-py==0.22.3 # via # jsonschema # referencing diff --git a/requirements/nightly.txt b/requirements/nightly.txt index 7ccb8b60..85bf1099 100644 --- a/requirements/nightly.txt +++ b/requirements/nightly.txt @@ -6,7 +6,7 @@ # pip-compile-multi # -r basetest.txt -asttokens==2.4.1 +asttokens==3.0.0 # via stack-data click==8.1.7 # via dask @@ -20,7 +20,7 @@ cyclebane==24.10.0 # via sciline cycler==0.12.1 # via matplotlib -dask==2024.11.2 +dask==2024.12.0 # via -r nightly.in decorator==5.1.1 # via ipython @@ -28,7 +28,7 @@ essreduce @ git+https://github.com/scipp/essreduce@main # via -r nightly.in executing==2.1.0 # via stack-data -fonttools==4.55.0 +fonttools==4.55.3 # via matplotlib fsspec==2024.10.0 # via dask @@ -42,7 +42,7 @@ importlib-metadata==8.5.0 # via dask ipydatawidgets==4.3.5 # via pythreejs -ipython==8.29.0 +ipython==8.30.0 # via ipywidgets ipywidgets==8.1.5 # via @@ -56,7 +56,7 @@ kiwisolver==1.4.7 # via matplotlib locket==1.0.0 # via partd -matplotlib==3.9.2 +matplotlib==3.10.0 # via # mpltoolbox # plopp diff --git a/src/ess/dream/data.py b/src/ess/dream/data.py index 48d00ec7..aefe8f5c 100644 --- a/src/ess/dream/data.py +++ b/src/ess/dream/data.py @@ -27,6 +27,10 @@ def _make_pooch(): "DREAM_simple_pwd_workflow/Cave_TOF_Monitor_diam_in_can.dat": "md5:ef24f4a4186c628574046e6629e31611", # noqa: E501 "DREAM_simple_pwd_workflow/Cave_TOF_Monitor_van_can.dat": "md5:e63456c347fb36a362a0b5ae2556b3cf", # noqa: E501 "DREAM_simple_pwd_workflow/Cave_TOF_Monitor_vana_inc_coh.dat": "md5:701d66792f20eb283a4ce76bae0c8f8f", # noqa: E501 + "stap_demo_october_2024/268227_00024779_Si_BC_offset_240_deg.hdf": "md5:d0d89bcae5bee0619e0333adfda57d70", # noqa: E501 + "stap_demo_october_2024/268227_00024779_Vana_inc_BC_offset_240_deg_wlgth.hdf": "md5:fbc8bde80c8889eea6ccea6f3f8eb9b8", # noqa: E501 + "stap_demo_october_2024/Cave_TOF_Monitor_hf_si_bc240.dat": "md5:8cf6c0a1b42185662ddc579eda07d1e6", # noqa: E501 + "stap_demo_october_2024/Cave_TOF_Monitor_hf_vanainc_bc240.dat": "md5:a9d5593d363a1c1fc51eb86757d6fa81", # noqa: E501 }, ) @@ -146,3 +150,37 @@ def simulated_monitor_empty_can() -> str: This is the DREAM cave monitor for ``simulated_empty_can``. """ return get_path("DREAM_simple_pwd_workflow/Cave_TOF_Monitor_van_can.dat") + + +def stap_demo_2024_si_sample() -> str: + """ + Path to a file containing detector event data for a McStas/Geant4 simulation with a + silicon sample. + """ + return get_path("stap_demo_october_2024/268227_00024779_Si_BC_offset_240_deg.hdf") + + +def stap_demo_2024_vanadium_sample() -> str: + """ + Path to a file containing detector event data for a McStas/Geant4 simulation with a + vanadium sample. + """ + return get_path( + "stap_demo_october_2024/268227_00024779_Vana_inc_BC_offset_240_deg_wlgth.hdf" + ) + + +def stap_demo_2024_si_monitor() -> str: + """ + Path to a file containing histogrammed monitor data for a McStas/Geant4 simulation + with a silicon sample. + """ + return get_path("stap_demo_october_2024/Cave_TOF_Monitor_hf_si_bc240.dat") + + +def stap_demo_2024_vanadium_monitor() -> str: + """ + Path to a file containing histogrammed monitor data for a McStas/Geant4 simulation + with a vanadium sample. + """ + return get_path("stap_demo_october_2024/Cave_TOF_Monitor_hf_vanainc_bc240.dat")