Reduction of ESTIA McStas data#

  • Audience: Instrument users, beginners

  • Prerequisites: Basic knowledge of Scipp

This notebook demonstrates the basic reflectometry data reduction workflow for ESTIA with simulated data. A workflow for data recorded at ESS would be very similar but is not yet available. The workflow:

  1. Converts the data to momentum transfer \(Q\).

  2. Normalizes by a reference measurement.

  3. Packages the results to be saved to and ORSO ORT file.

The data is available through the ESSreflectometry package but accessing it requires the pooch package. If you get an error about a missing module pooch, you can install it with !pip install pooch.

[1]:
import scipp as sc

from ess.estia.data import estia_mcstas_example
from ess.estia import EstiaMcStasWorkflow
from ess.reflectometry.types import *

Create and configure the workflow#

We begin by creating the ESTIA (McStas) workflow object which is a skeleton for reducing ESTIA data with pre-configured steps:

[2]:
wf = EstiaMcStasWorkflow()

We then need to set the missing parameters which are specific to each experiment (the keys are types defined in ess.reflectometry.types).

[3]:
# Specify input data files:
# (The choice of 'Ni/Ti-multilayer' file number 3 is arbitrary.)
wf[Filename[SampleRun]] = estia_mcstas_example('Ni/Ti-multilayer')[3]
wf[Filename[ReferenceRun]] = estia_mcstas_example('reference')

# Select a region of interest:
wf[YIndexLimits] = sc.scalar(35), sc.scalar(64)
wf[ZIndexLimits] = sc.scalar(0), sc.scalar(48 * 32)
wf[BeamDivergenceLimits] = sc.scalar(-0.75, unit='deg'), sc.scalar(0.75, unit='deg')

# Configure the binning of intermediate and final results:
wf[WavelengthBins] = sc.geomspace('wavelength', 3.5, 12, 2001, unit='angstrom')
wf[QBins] = 1000

# There is no proton current data in the McStas files, here we just add some fake proton current
# data to make the workflow run.
wf[ProtonCurrent[SampleRun]] = sc.DataArray(
    sc.array(dims=('time',), values=[]),
    coords={'time': sc.array(dims=('time',), values=[], unit='s')})
wf[ProtonCurrent[ReferenceRun]] = sc.DataArray(
    sc.array(dims=('time',), values=[]),
    coords={'time': sc.array(dims=('time',), values=[], unit='s')})

We can visualize the workflow as a graph. This can help us understand how the data will be reduced. (ReflectivityOverQ is the key of the output data.)

[4]:
wf.visualize(ReflectivityOverQ, graph_attr={'rankdir': "LR"})
[4]:
../../_images/user-guide_estia_estia-mcstas-reduction_7_0.svg

The workflow is a Sciline pipeline. See the documentation of Sciline for more information and how to modify and extend the workflow.

Use the reduction workflow#

We call wf.compute(targets) to compute the result:

[5]:
reflectivity = wf.compute(ReflectivityOverQ)

The reflectivity is still event data. We can histogram it and plot it:

[6]:
reflectivity.hist().plot(norm='log', vmin=1e-8)
/home/runner/work/essreflectometry/essreflectometry/.tox/docs/lib/python3.10/site-packages/matplotlib/axes/_axes.py:3828: RuntimeWarning: invalid value encountered in add
  low, high = dep + np.vstack([-(1 - lolims), 1 - uplims]) * err
[6]:
../../_images/user-guide_estia_estia-mcstas-reduction_11_1.svg

Saving to ORSO ORT file#

Ultimately, we want to save the reduced data to a file. The workflow supports building an ORSO dataset from the reduced data: OrsoIofQDataset. We require some additional imports:

[7]:
from orsopy import fileio

from ess.reflectometry import orso
[8]:
wf.visualize(orso.OrsoIofQDataset, graph_attr={'rankdir': "LR"})
[8]:
../../_images/user-guide_estia_estia-mcstas-reduction_14_0.svg

We can see from the graph that some nodes are missing (red boxes). These need to be manually provided as they cannot be deduced from the input. Further, McStas files do not contain all required metadata, so that needs to be provided manually as well.

[9]:
wf[orso.Beamline] = orso.Beamline(name='ESTIA', facility='ESS')
wf[orso.Measurement] = orso.Measurement(
    title='McStas Simulation, Ni/Ti-multilayer',
)
wf[orso.OrsoSample] = orso.OrsoSample(
    fileio.data_source.Sample(name='Ni/Ti multilayer')
)
wf[orso.OrsoCreator] = orso.OrsoCreator(
    fileio.base.Person(
        name='Max Mustermann',
        affiliation='European Spallation Source ERIC',
        contact='max.mustermann@ess.eu',
    )
)
wf[orso.OrsoOwner] = wf[orso.OrsoCreator]

Now that we have these additional parameters, we can construct the ORSO dataset: (Note that this will re-run the reduction procedure to ensure that all data is consistent.)

[10]:
dataset = wf.compute(orso.OrsoIofQDataset)

The dataset has not been written to disk yet. For that, simply call save:

[11]:
dataset.save('estia_reduced_iofq.ort')

Next, consider reading the ESTIA advanced McStas reduction guide which demonstrates how multiple files can be reduced together and how to make different types of plots.