Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0",
"metadata": {},
"source": [
"# FREIA detector data\n",
"\n",
"Visualize detector images, arrival-time distributions, and wavelength spectra. Wavelengths are reconstructed using the WFM chopper settings."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib widget\n",
"import plopp as pp\n",
"import scipp as sc\n",
"\n",
"from ess import freia\n",
"from ess.freia import data\n",
"from ess.reduce.nexus.types import DiskChoppers, Filename, RawDetector\n",
"from ess.reduce.unwrap import (\n",
" ChopperFrameSequence,\n",
" DistanceResolution,\n",
" PulsePeriod,\n",
" TimeResolution,\n",
" WavelengthDetector,\n",
")\n",
"from ess.reduce.unwrap.types import KeepEventTimeOffset\n",
"from ess.reflectometry.types import SampleRun"
]
},
{
"cell_type": "markdown",
"id": "2",
"metadata": {},
"source": [
"## Select a run\n",
"\n",
"Download the example sample run and set the resolution used to reconstruct wavelengths. The file is cached locally by `pooch` (`pip install pooch`). To use your own data, replace the download function with a file path."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3",
"metadata": {},
"outputs": [],
"source": [
"freia_mcstas = freia.FreiaMcStasWorkflow(wavelength_from='analytical')\n",
"freia_mcstas[Filename[SampleRun]] = data.freia_mcstas_reference_run()\n",
"freia_mcstas[KeepEventTimeOffset] = True\n",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll upload these files to the pooch repo

"freia_mcstas[TimeResolution] = sc.scalar(20.0, unit='us')\n",
"freia_mcstas[DistanceResolution] = sc.scalar(0.1, unit='m')"
]
},
{
"cell_type": "markdown",
"id": "4",
"metadata": {},
"source": [
"## Inspect the WFM chopper cascade\n",
"\n",
"Inspect the chopper timing used to reconstruct wavelengths. For a non-WFM run, call `freia_mcstas.insert(freia.mcstas.non_wfm_choppers)` before computing wavelengths. Other configurations can be assigned to `freia_mcstas[DiskChoppers[SampleRun]]`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5",
"metadata": {},
"outputs": [],
"source": [
"choppers = freia_mcstas.compute(DiskChoppers[SampleRun])\n",
"sc.DataGroup(choppers)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6",
"metadata": {},
"outputs": [],
"source": [
"frames = freia_mcstas.compute(ChopperFrameSequence[SampleRun])\n",
"frames.draw()"
]
},
{
"cell_type": "markdown",
"id": "7",
"metadata": {},
"source": [
"## Load and unwrap the detector events\n",
"\n",
"Compute wavelengths from the event arrival times and chopper transmission bands."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8",
"metadata": {},
"outputs": [],
"source": [
"results = freia_mcstas.compute((RawDetector[SampleRun], WavelengthDetector[SampleRun]))\n",
"raw = results[RawDetector[SampleRun]]\n",
"unwrapped = results[WavelengthDetector[SampleRun]]\n",
"raw"
]
},
{
"cell_type": "markdown",
"id": "9",
"metadata": {},
"source": [
"## Detector image and arrival times\n",
"\n",
"The image uses `longitude` and `height` in the detector's local frame. Intensities are sums of event weights."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "10",
"metadata": {},
"outputs": [],
"source": [
"detector_image = raw.hist(longitude=120, height=64, dim=raw.dims)\n",
"pp.plot(detector_image, norm='log', title='FREIA detector', vmin=1e-1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "11",
"metadata": {},
"outputs": [],
"source": [
"pulse_period = freia_mcstas.compute(PulsePeriod).to(unit='s').value\n",
"arrival_times = raw.hist(\n",
" event_time_offset=sc.linspace(\n",
" 'event_time_offset', 0.0, pulse_period, 501, unit='s'\n",
" ),\n",
" dim=raw.dims,\n",
")\n",
"arrival_times.coords['event_time_offset'] = arrival_times.coords[\n",
" 'event_time_offset'\n",
"].to(unit='ms')\n",
"pp.plot(arrival_times, title='Arrival time within the source period')"
]
},
{
"cell_type": "markdown",
"id": "12",
"metadata": {},
"source": [
"## Wavelengths from analytical frame unwrapping\n",
"\n",
"The chopper cascade and arrival times determine the wavelengths. Events outside the modeled transmission bands or above the workflow's relative wavelength uncertainty threshold have NaN wavelengths and do not contribute to the wavelength histograms. Inspect the assigned-event count when assessing the result."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13",
"metadata": {},
"outputs": [],
"source": [
"event_wavelengths = unwrapped.bins.constituents['data'].coords['wavelength']\n",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this differently than having to go via .bins.constituents?
Am I right in understanding that you want to remove the wavelengths that have been assigned NaN?

Can we instead do something like unwrapped.hist(wavelength=1).sum() and unwrapped.sum() to get the N events out of M?

Histogramming into 1 bin should discard all the NaNs.

"valid = sc.isfinite(event_wavelengths)\n",
"print(f'{sc.sum(valid).value:,} / {valid.size:,} events have an assigned wavelength')\n",
"\n",
"wavelength_bins = sc.linspace('wavelength', 1.0, 12.0, 441, unit='angstrom')\n",
"spectrum = unwrapped.hist(wavelength=wavelength_bins, dim=unwrapped.dims)\n",
"pp.plot(spectrum, title='FREIA wavelength spectrum')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "14",
"metadata": {},
"outputs": [],
"source": [
"wavelength_image = unwrapped.hist(\n",
" wavelength=wavelength_bins, longitude=120, dim=unwrapped.dims\n",
")\n",
"pp.plot(wavelength_image, norm='log', title='Wavelength across the detector', vmin=1e0)"
]
}
],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth adding at the end of the notebook an inspector plot, where we histogram in longitude, height and wavelength? And then draw some rectangles around some regions?

"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",
"version": "3.12.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading
Loading