Introduction to Sciline#
Data processing workflow management tool.
scipp.github.io/sciline/
It is worth taking your time going through this notebook, do not try to rush it.
Sciline is an open-source library developed by ESS for managing and visualizing data processing workflows (sometimes called “pipelines”).
It defines workflows as directed acyclic graphs (DAGs) where the nodes are inputs, intermediate results, or final results, and edges are dependencies between the nodes.
This has some benefits:
Any (named) intermediate result in the pipeline can be computed.
The dependencies between intermediate results can be visualized.
Implementations of intermediate result can be replaced.
Results that are expensive to compute can be cached.
Certainty that the computed result has not been corrupted by running jupyter cells out of order.
Terminology#
A Sciline workflow (or “pipeline”) is defined by a set of transformations or providers that specify what inputs are needed to compute one specific output quantity.
The input and output quantities of the providers are called domain types.
A provider is a python function with type annotations:
# Example provider
def load_run(
run_number: RunNumber,
proposal_number: ProposalNumber,
data_dir_path: DataPath,
) -> LoadedNexusData:
filename = f'{proposal_number}_{run_number:06d}.hdf'
path = os.path.join(data_dir_path, filename)
data = scippnexus.load(path)
return data
In the above example, to compute the LoadedNexusData quantity the RunNumber, ProposalNumber and the DataPath quantities are needed.
LoadedNexusData, RunNumber, ProposalNumber and DataPath are “domain types”.
The domain types are the nodes in the workflow graph, and they represent the inputs, intermediate results, or final results of the workflow.
Inputs, intermediate results, and final results#
A typical data reduction workflow has some “Inputs”, some “Intermediate results” and some “Final results”.
Sciline does not distinguish between those, but it is useful to make a loose distinction:
Inputs are typically:
The name of one or more NeXus files.
Parameters defining a region of interest (ROI),
for example the wavelength range.
The number of histogram bins.
Intermediate results are typically:
List of events with associated coordinates, masks, and weights.
“Coordinates” such as wavelength, scattering angle, etc.
Monitor wavelength histogram.
Various calibration factors that are computed or loaded from file.
Final results are typically:
Curve describing the scattering cross section \(S(Q)\) as a function of momentum transfer (SANS).
List of peaks and associated intensities (diffraction).
Etc.
How does Sciline know how to build the graph?#
Each domain type is unique, and given a list of all functions to be used in the workflow, Sciline can figure out how to connect the nodes in the graph.
Think of it like puzzle pieces that fit into each other:
Example#
import os
from typing import NewType
import sciline as sl
import scipp as sc
from scippneutron.conversion.graph.beamline import beamline
from scippneutron.conversion.graph.tof import elastic
import sans_utils as utils
graph = {**beamline(scatter=True), **elastic("tof")}
Creating a pipeline#
We start by by defining the domain types: the quantities representing input parameters, intermediate results and the final results of the pipeline.
Foldername = NewType("Foldername", str)
"""Folder name for measurements."""
RawData = NewType("RawData", sc.DataArray)
"""Raw loaded data."""
CoordTransformGraph = NewType("CoordTransformGraph", dict)
"""Graph describing coordinate transformations."""
WavelengthData = NewType("WavelengthData", sc.DataArray)
"""Data with wavelength coordinate."""
QData = NewType("Qdata", sc.DataArray)
"""Data with Q coordinate."""
QBins = NewType("QBins", sc.Variable)
"""Bin edges in the Q dimension."""
QHistogram = NewType("QHistogram", sc.DataArray)
"""Data histogrammed in Q bins."""
Next, we create the ‘provider’ functions: the operations that determine how do we get from one domain type to the next.
def load(folder: Foldername) -> RawData:
"""Load raw data from file"""
return utils.load_sans(folder)
def to_wavelength(data: RawData, graph: CoordTransformGraph) -> WavelengthData:
"""Compute wavelength for events"""
return data.transform_coords("wavelength", graph=graph)
def to_Q(data: WavelengthData, graph: CoordTransformGraph) -> QData:
"""Compute Q for events"""
return data.transform_coords("Q", graph=graph)
def to_histogram(events: QData, qbins: QBins) -> QHistogram:
"""Histogram data in Q bins"""
return events.hist(Q=qbins)
Finally, we build the workflow (also known as a ‘pipeline’) by supplying the list of our functions defined above:
workflow = sl.Pipeline(
# List the providers that make up the workflow.
(load, to_wavelength, to_Q, to_histogram),
)
workflow.visualize(graph_attr={"rankdir": "LR"})
Some domain types are visualized in red color and with dashed border, those are the domain types that lack a definition.
Setting parameters#
To set a parameter on the workflow, we use the setitem operator [] (as one would do with a python dict):
workflow[QBins] = sc.linspace("Q", 5.0e-3, 0.19, 201, unit="1/angstrom")
workflow[Foldername] = utils.fetch_data("3-mcstas/SANS_with_sample_many_neutrons")
workflow[CoordTransformGraph] = graph
We can now visualize the workflow again and see that the red boxes have now turned black;
all parameters required to compute the QHistogram have been set.
workflow.visualize(graph_attr={"rankdir": "LR"})
Computing quantities#
Until now, not computations have taken place. We have simply set-up the framework for the reduction in the shape of a task-graph, but nothing has been computed yet.
Building and manipulating the graph is very cheap, and only once we are satisfied with it should we then proceed with computing the final result.
This is done by calling the compute method:
q_hist = workflow.compute(QHistogram)
q_hist
- Q: 200
- L1()float64m150.0
Values:
array(150.) - Q(Q [bin-edge])float641/Å0.005, 0.006, ..., 0.189, 0.19
Values:
array([0.005 , 0.005925, 0.00685 , 0.007775, 0.0087 , 0.009625, 0.01055 , 0.011475, 0.0124 , 0.013325, 0.01425 , 0.015175, 0.0161 , 0.017025, 0.01795 , 0.018875, 0.0198 , 0.020725, 0.02165 , 0.022575, 0.0235 , 0.024425, 0.02535 , 0.026275, 0.0272 , 0.028125, 0.02905 , 0.029975, 0.0309 , 0.031825, 0.03275 , 0.033675, 0.0346 , 0.035525, 0.03645 , 0.037375, 0.0383 , 0.039225, 0.04015 , 0.041075, 0.042 , 0.042925, 0.04385 , 0.044775, 0.0457 , 0.046625, 0.04755 , 0.048475, 0.0494 , 0.050325, 0.05125 , 0.052175, 0.0531 , 0.054025, 0.05495 , 0.055875, 0.0568 , 0.057725, 0.05865 , 0.059575, 0.0605 , 0.061425, 0.06235 , 0.063275, 0.0642 , 0.065125, 0.06605 , 0.066975, 0.0679 , 0.068825, 0.06975 , 0.070675, 0.0716 , 0.072525, 0.07345 , 0.074375, 0.0753 , 0.076225, 0.07715 , 0.078075, 0.079 , 0.079925, 0.08085 , 0.081775, 0.0827 , 0.083625, 0.08455 , 0.085475, 0.0864 , 0.087325, 0.08825 , 0.089175, 0.0901 , 0.091025, 0.09195 , 0.092875, 0.0938 , 0.094725, 0.09565 , 0.096575, 0.0975 , 0.098425, 0.09935 , 0.100275, 0.1012 , 0.102125, 0.10305 , 0.103975, 0.1049 , 0.105825, 0.10675 , 0.107675, 0.1086 , 0.109525, 0.11045 , 0.111375, 0.1123 , 0.113225, 0.11415 , 0.115075, 0.116 , 0.116925, 0.11785 , 0.118775, 0.1197 , 0.120625, 0.12155 , 0.122475, 0.1234 , 0.124325, 0.12525 , 0.126175, 0.1271 , 0.128025, 0.12895 , 0.129875, 0.1308 , 0.131725, 0.13265 , 0.133575, 0.1345 , 0.135425, 0.13635 , 0.137275, 0.1382 , 0.139125, 0.14005 , 0.140975, 0.1419 , 0.142825, 0.14375 , 0.144675, 0.1456 , 0.146525, 0.14745 , 0.148375, 0.1493 , 0.150225, 0.15115 , 0.152075, 0.153 , 0.153925, 0.15485 , 0.155775, 0.1567 , 0.157625, 0.15855 , 0.159475, 0.1604 , 0.161325, 0.16225 , 0.163175, 0.1641 , 0.165025, 0.16595 , 0.166875, 0.1678 , 0.168725, 0.16965 , 0.170575, 0.1715 , 0.172425, 0.17335 , 0.174275, 0.1752 , 0.176125, 0.17705 , 0.177975, 0.1789 , 0.179825, 0.18075 , 0.181675, 0.1826 , 0.183525, 0.18445 , 0.185375, 0.1863 , 0.187225, 0.18815 , 0.189075, 0.19 ]) - incident_beam()vector3m[ 0. 0. 150.]
Values:
array([ 0., 0., 150.]) - sample_position()vector3m[0. 0. 0.]
Values:
array([0., 0., 0.]) - source_position()vector3m[ 0. 0. -150.]
Values:
array([ 0., 0., -150.])
- (Q)float64counts2729.742, 4071.837, ..., 0.419, 0.045σ = 34.391, 47.398, ..., 0.109, 0.009
Values:
array([2.72974237e+03, 4.07183737e+03, 3.96718862e+03, 3.89124955e+03, 3.80164008e+03, 3.67807453e+03, 3.52326835e+03, 3.29514884e+03, 3.19940041e+03, 3.14971520e+03, 3.02506958e+03, 2.88396277e+03, 2.66118161e+03, 2.53163776e+03, 2.41394262e+03, 2.28977330e+03, 2.07685305e+03, 1.90423830e+03, 1.74687194e+03, 1.59168108e+03, 1.25564850e+03, 1.23361572e+03, 8.66285997e+02, 6.64304129e+02, 4.92014333e+02, 3.50413467e+02, 2.46102338e+02, 2.24153320e+02, 2.23885961e+02, 2.41489418e+02, 2.34410810e+02, 2.34401477e+02, 2.35054661e+02, 2.57658721e+02, 2.27001704e+02, 1.88015026e+02, 1.91104457e+02, 1.50309728e+02, 1.27540925e+02, 9.63903329e+01, 7.57636628e+01, 5.26868469e+01, 4.56785359e+01, 3.63682838e+01, 2.75738161e+01, 2.40292114e+01, 1.99115255e+01, 1.87975614e+01, 1.86958807e+01, 1.93381493e+01, 2.25731544e+01, 2.46014136e+01, 2.73478862e+01, 2.93031758e+01, 3.54386011e+01, 3.35298376e+01, 3.57868767e+01, 4.09468027e+01, 4.12233726e+01, 4.43668216e+01, 4.83627729e+01, 4.45983845e+01, 4.33080569e+01, 4.52745987e+01, 4.25102072e+01, 5.14532314e+01, 4.91291670e+01, 4.27051313e+01, 4.50136805e+01, 4.46079086e+01, 4.08642003e+01, 3.72661482e+01, 3.64436504e+01, 3.07974096e+01, 3.12425553e+01, 3.24481799e+01, 2.73734421e+01, 2.07840466e+01, 2.04611163e+01, 1.77629617e+01, 1.71598671e+01, 1.61730021e+01, 1.54056295e+01, 1.60936218e+01, 1.72087609e+01, 1.72829356e+01, 1.64599511e+01, 1.56396260e+01, 1.41352107e+01, 1.52486599e+01, 1.26459880e+01, 1.72002262e+01, 1.96248626e+01, 1.95014437e+01, 2.15019178e+01, 2.33989080e+01, 2.12985070e+01, 2.02094407e+01, 1.82456888e+01, 1.87728922e+01, 2.21676136e+01, 1.86479519e+01, 2.02860477e+01, 1.89767586e+01, 2.12063640e+01, 1.95735834e+01, 1.67284563e+01, 2.03220247e+01, 2.12473696e+01, 1.82170720e+01, 2.13471395e+01, 1.97899398e+01, 1.73949648e+01, 1.90921897e+01, 1.94319163e+01, 2.16560924e+01, 1.56146377e+01, 1.93097118e+01, 1.62392677e+01, 1.57373741e+01, 1.47462106e+01, 1.44770307e+01, 1.62958929e+01, 1.31343524e+01, 1.61244496e+01, 1.46280003e+01, 1.54331607e+01, 1.76933309e+01, 1.42260521e+01, 1.76359505e+01, 1.62185435e+01, 1.87482984e+01, 1.69934900e+01, 1.52698921e+01, 2.01045034e+01, 1.67727863e+01, 1.80520741e+01, 1.53005178e+01, 1.44254374e+01, 1.82446745e+01, 1.65682690e+01, 1.76288355e+01, 1.67338403e+01, 1.76189905e+01, 1.76716326e+01, 1.62512102e+01, 1.67895223e+01, 1.59882241e+01, 1.38324827e+01, 1.61281895e+01, 1.77625320e+01, 1.43177435e+01, 1.67516638e+01, 1.63389229e+01, 1.22747926e+01, 1.65744057e+01, 1.66453507e+01, 1.34394404e+01, 1.40480306e+01, 1.26103516e+01, 1.47370521e+01, 1.21776273e+01, 1.38911794e+01, 1.13118770e+01, 1.50950800e+01, 1.38275507e+01, 1.50275579e+01, 9.90839680e+00, 1.27541005e+01, 1.04657295e+01, 1.19202924e+01, 9.63832937e+00, 8.10519543e+00, 1.34445223e+01, 7.62032281e+00, 1.09081873e+01, 8.11793570e+00, 9.55968791e+00, 8.14524996e+00, 5.62046109e+00, 5.79273670e+00, 3.36388006e+00, 5.39154324e+00, 7.58935094e+00, 5.58888833e+00, 4.74662947e+00, 3.81061128e+00, 3.61654794e+00, 1.90361561e+00, 2.51216284e+00, 3.14619206e+00, 2.43321616e+00, 1.84364324e+00, 2.18131726e+00, 2.29937419e+00, 8.86200299e-01, 6.29927477e-01, 9.59958138e-01, 4.18974267e-01, 4.49784109e-02])
Variances (σ²):
array([1.18271398e+03, 2.24653215e+03, 2.46084166e+03, 2.79182223e+03, 3.09952887e+03, 3.31877065e+03, 3.51882590e+03, 3.59403563e+03, 3.75781306e+03, 4.04016715e+03, 4.11267226e+03, 4.18763665e+03, 4.02835918e+03, 4.05608684e+03, 3.97283204e+03, 3.89081401e+03, 3.63714227e+03, 3.31024572e+03, 3.06771829e+03, 2.83638514e+03, 2.21630998e+03, 2.21163413e+03, 1.52307222e+03, 1.18372863e+03, 8.42743550e+02, 5.54786047e+02, 3.78140024e+02, 3.03288752e+02, 2.73362684e+02, 2.75115324e+02, 2.32848446e+02, 2.15537958e+02, 2.02997760e+02, 2.21348223e+02, 1.65479271e+02, 1.18559698e+02, 1.07344519e+02, 7.25307374e+01, 5.53554268e+01, 3.48654614e+01, 2.20806521e+01, 1.12541900e+01, 7.31032941e+00, 5.20821442e+00, 2.51578299e+00, 1.59168074e+00, 1.01966399e+00, 8.82987846e-01, 8.91356117e-01, 9.76224321e-01, 1.50818201e+00, 2.16213326e+00, 2.77885994e+00, 3.52570526e+00, 4.94367841e+00, 5.15720149e+00, 6.08935046e+00, 8.12890686e+00, 8.78204707e+00, 1.03662293e+01, 1.22875058e+01, 1.11308471e+01, 1.12497290e+01, 1.24956310e+01, 1.13812596e+01, 1.49255128e+01, 1.38528178e+01, 1.17695279e+01, 1.19924762e+01, 1.17785174e+01, 1.05544479e+01, 8.51503502e+00, 8.07147524e+00, 6.59274761e+00, 6.17571123e+00, 5.69738777e+00, 4.36398533e+00, 2.54988992e+00, 2.36489865e+00, 1.86559300e+00, 1.59092941e+00, 1.36204807e+00, 1.23700995e+00, 1.18313671e+00, 1.41835544e+00, 1.38261825e+00, 1.26313591e+00, 1.25407807e+00, 1.10099065e+00, 1.29733502e+00, 9.61136179e-01, 1.80042379e+00, 2.43496597e+00, 2.28335302e+00, 3.05830193e+00, 3.67323058e+00, 3.26989597e+00, 2.89874215e+00, 2.58100203e+00, 2.80342317e+00, 4.24362124e+00, 3.22345334e+00, 3.37656574e+00, 3.35354269e+00, 4.20717560e+00, 3.60569547e+00, 2.68471570e+00, 3.81498121e+00, 3.78752077e+00, 2.96070362e+00, 3.82596399e+00, 3.53559968e+00, 2.73560388e+00, 3.49427464e+00, 3.37176452e+00, 3.51293740e+00, 1.97872010e+00, 2.98374734e+00, 2.29583807e+00, 2.12812835e+00, 1.87254291e+00, 1.87276497e+00, 2.50256119e+00, 1.64982894e+00, 2.16344780e+00, 1.90462291e+00, 2.18859465e+00, 2.86167717e+00, 1.97154177e+00, 2.86399908e+00, 2.84008017e+00, 3.88298704e+00, 3.19124591e+00, 2.63138049e+00, 4.45093976e+00, 3.01209448e+00, 3.89027915e+00, 2.90446887e+00, 2.29931033e+00, 3.81563643e+00, 3.16687774e+00, 3.94335436e+00, 3.79874552e+00, 3.68594159e+00, 3.80204361e+00, 3.61146024e+00, 3.87689978e+00, 3.29053836e+00, 2.50156703e+00, 3.63331258e+00, 4.07330062e+00, 2.73145030e+00, 3.64998974e+00, 3.37505994e+00, 2.35182951e+00, 3.76885476e+00, 3.59748223e+00, 2.42305683e+00, 2.91431476e+00, 2.35170548e+00, 3.02067399e+00, 2.39314553e+00, 3.42808108e+00, 2.09231475e+00, 3.33518745e+00, 3.86758277e+00, 4.08337887e+00, 1.90938956e+00, 3.57754955e+00, 2.79315012e+00, 3.54709219e+00, 2.77823483e+00, 1.90722948e+00, 4.70525479e+00, 1.99488574e+00, 3.92706755e+00, 2.18118845e+00, 3.57502354e+00, 2.76842468e+00, 1.68984068e+00, 1.46577780e+00, 1.90809285e-01, 1.43027543e+00, 2.63476367e+00, 1.88706709e+00, 1.62644365e+00, 1.24291962e+00, 8.03869571e-01, 3.15189630e-02, 4.63543706e-01, 1.32232211e+00, 5.06878141e-01, 5.33925402e-01, 6.59093547e-01, 8.92936421e-01, 1.73273164e-02, 1.14405438e-02, 3.31029083e-01, 1.17812501e-02, 7.99953070e-05])
q_hist.plot()
Intermediate results#
One of the most powerful features about sciline is that once we have built a graph,
any step (node) in the graph can be inspected.
This is extremely useful for looking at intermediate results, while debugging a workflow for instance.
Computing intermediate results is also done with the compute method, but we simply pass as the argument the type that corresponds to the quantity we wish to compute.
wavelength_data = workflow.compute(WavelengthData)
wavelength_data
- event: 21698488
- L1()float64m150.0
Values:
array(150.) - L2(event)float64m3.013, 3.012, ..., 3.005, 3.005
Values:
array([3.01317307, 3.01247634, 3.01251313, ..., 3.00541293, 3.00534931, 3.00538394], shape=(21698488,)) - Ltotal(event)float64m153.013, 153.012, ..., 153.005, 153.005
Values:
array([153.01317307, 153.01247634, 153.01251313, ..., 153.00541293, 153.00534931, 153.00538394], shape=(21698488,)) - incident_beam()vector3m[ 0. 0. 150.]
Values:
array([ 0., 0., 150.]) - position(event)vector3m[0. 0.28144614 3. ], [0. 0.27388628 3. ], ..., [0. 0.17923303 3. ], [0. 0.17981275 3. ]
Values:
array([[0. , 0.28144614, 3. ], [0. , 0.27388628, 3. ], [0. , 0.27429062, 3. ], ..., [0. , 0.18029663, 3. ], [0. , 0.17923303, 3. ], [0. , 0.17981275, 3. ]], shape=(21698488, 3)) - sample_position()vector3m[0. 0. 0.]
Values:
array([0., 0., 0.]) - scattered_beam(event)vector3m[0. 0.28144614 3. ], [0. 0.27388628 3. ], ..., [0. 0.17923303 3. ], [0. 0.17981275 3. ]
Values:
array([[0. , 0.28144614, 3. ], [0. , 0.27388628, 3. ], [0. , 0.27429062, 3. ], ..., [0. , 0.18029663, 3. ], [0. , 0.17923303, 3. ], [0. , 0.17981275, 3. ]], shape=(21698488, 3)) - source_position()vector3m[ 0. 0. -150.]
Values:
array([ 0., 0., -150.]) - tof(event)float64ms251.226, 251.239, ..., 233.352, 233.356
Values:
array([251.22550766, 251.23940373, 251.24018643, ..., 233.34365168, 233.35173882, 233.35641044], shape=(21698488,)) - wavelength(event)float64Å6.495, 6.496, ..., 6.033, 6.034
Values:
array([6.49523588, 6.49562473, 6.4956434 , ..., 6.03322068, 6.03343228, 6.03355171], shape=(21698488,)) - x(event)float64m0.0, 0.0, ..., 0.0, 0.0
Values:
array([0., 0., 0., ..., 0., 0., 0.], shape=(21698488,)) - y(event)float64m0.281, 0.274, ..., 0.179, 0.180
Values:
array([0.28144614, 0.27388628, 0.27429062, ..., 0.18029663, 0.17923303, 0.17981275], shape=(21698488,))
- (event)float64counts1.126e-11, 9.608e-16, ..., 1.223e-90, 1.131e-94σ = 1.126e-11, 9.608e-16, ..., 1.223e-90, 1.131e-94
Values:
array([1.12600052e-11, 9.60753256e-16, 8.19757010e-20, ..., 1.32191179e-86, 1.22278950e-90, 1.13109979e-94], shape=(21698488,))
Variances (σ²):
array([1.26787717e-022, 9.23046820e-031, 6.72001556e-039, ..., 1.74745078e-172, 1.49521415e-180, 1.27938674e-188], shape=(21698488,))
Computing multiple results#
It is also possible to request more than one result in one go.
This is useful because whenever we compute a quantity, sciline walks the entire graph all over again; nothing is cached.
This default behaviour ensures the correctness and reproducibility of results.
So when we first computed the QHistogram and then the WavelengthData above in 2 separate compute calls,
we actually loaded the file twice.
To avoid this, we can request both targets inside the call to compute, and the file will only be loaded once (the scheduler will identify which parts of the graph are needed for which result and will not repeat branches used by both).
two_results = workflow.compute((WavelengthData, QHistogram))
two_results
{__main__.WavelengthData: <scipp.DataArray>
Dimensions: Sizes[event:21698488, ]
Coordinates:
L1 float64 [m] () 150
L2 float64 [m] (event) [3.01317, 3.01248, ..., 3.00535, 3.00538]
Ltotal float64 [m] (event) [153.013, 153.012, ..., 153.005, 153.005]
incident_beam vector3 [m] () (0, 0, 150)
position vector3 [m] (event) [(0, 0.281446, 3), (0, 0.273886, 3), ..., (0, 0.179233, 3), (0, 0.179813, 3)]
sample_position vector3 [m] () (0, 0, 0)
scattered_beam vector3 [m] (event) [(0, 0.281446, 3), (0, 0.273886, 3), ..., (0, 0.179233, 3), (0, 0.179813, 3)]
source_position vector3 [m] () (0, 0, -150)
tof float64 [ms] (event) [251.226, 251.239, ..., 233.352, 233.356]
* wavelength float64 [Å] (event) [6.49524, 6.49562, ..., 6.03343, 6.03355]
* x float64 [m] (event) [0, 0, ..., 0, 0]
* y float64 [m] (event) [0.281446, 0.273886, ..., 0.179233, 0.179813]
Data:
float64 [counts] (event) [1.126e-11, 9.60753e-16, ..., 1.22279e-90, 1.1311e-94] [1.26788e-22, 9.23047e-31, ..., 1.49521e-180, 1.27939e-188]
,
__main__.QHistogram: <scipp.DataArray>
Dimensions: Sizes[Q:200, ]
Coordinates:
L1 float64 [m] () 150
* Q float64 [1/Å] (Q [bin-edge]) [0.005, 0.005925, ..., 0.189075, 0.19]
incident_beam vector3 [m] () (0, 0, 150)
sample_position vector3 [m] () (0, 0, 0)
source_position vector3 [m] () (0, 0, -150)
Data:
float64 [counts] (Q) [2729.74, 4071.84, ..., 0.418974, 0.0449784] [1182.71, 2246.53, ..., 0.0117813, 7.99953e-05]
}
The results are stored in a dictionary where the keys are just the requested types:
two_results[QHistogram]
- Q: 200
- L1()float64m150.0
Values:
array(150.) - Q(Q [bin-edge])float641/Å0.005, 0.006, ..., 0.189, 0.19
Values:
array([0.005 , 0.005925, 0.00685 , 0.007775, 0.0087 , 0.009625, 0.01055 , 0.011475, 0.0124 , 0.013325, 0.01425 , 0.015175, 0.0161 , 0.017025, 0.01795 , 0.018875, 0.0198 , 0.020725, 0.02165 , 0.022575, 0.0235 , 0.024425, 0.02535 , 0.026275, 0.0272 , 0.028125, 0.02905 , 0.029975, 0.0309 , 0.031825, 0.03275 , 0.033675, 0.0346 , 0.035525, 0.03645 , 0.037375, 0.0383 , 0.039225, 0.04015 , 0.041075, 0.042 , 0.042925, 0.04385 , 0.044775, 0.0457 , 0.046625, 0.04755 , 0.048475, 0.0494 , 0.050325, 0.05125 , 0.052175, 0.0531 , 0.054025, 0.05495 , 0.055875, 0.0568 , 0.057725, 0.05865 , 0.059575, 0.0605 , 0.061425, 0.06235 , 0.063275, 0.0642 , 0.065125, 0.06605 , 0.066975, 0.0679 , 0.068825, 0.06975 , 0.070675, 0.0716 , 0.072525, 0.07345 , 0.074375, 0.0753 , 0.076225, 0.07715 , 0.078075, 0.079 , 0.079925, 0.08085 , 0.081775, 0.0827 , 0.083625, 0.08455 , 0.085475, 0.0864 , 0.087325, 0.08825 , 0.089175, 0.0901 , 0.091025, 0.09195 , 0.092875, 0.0938 , 0.094725, 0.09565 , 0.096575, 0.0975 , 0.098425, 0.09935 , 0.100275, 0.1012 , 0.102125, 0.10305 , 0.103975, 0.1049 , 0.105825, 0.10675 , 0.107675, 0.1086 , 0.109525, 0.11045 , 0.111375, 0.1123 , 0.113225, 0.11415 , 0.115075, 0.116 , 0.116925, 0.11785 , 0.118775, 0.1197 , 0.120625, 0.12155 , 0.122475, 0.1234 , 0.124325, 0.12525 , 0.126175, 0.1271 , 0.128025, 0.12895 , 0.129875, 0.1308 , 0.131725, 0.13265 , 0.133575, 0.1345 , 0.135425, 0.13635 , 0.137275, 0.1382 , 0.139125, 0.14005 , 0.140975, 0.1419 , 0.142825, 0.14375 , 0.144675, 0.1456 , 0.146525, 0.14745 , 0.148375, 0.1493 , 0.150225, 0.15115 , 0.152075, 0.153 , 0.153925, 0.15485 , 0.155775, 0.1567 , 0.157625, 0.15855 , 0.159475, 0.1604 , 0.161325, 0.16225 , 0.163175, 0.1641 , 0.165025, 0.16595 , 0.166875, 0.1678 , 0.168725, 0.16965 , 0.170575, 0.1715 , 0.172425, 0.17335 , 0.174275, 0.1752 , 0.176125, 0.17705 , 0.177975, 0.1789 , 0.179825, 0.18075 , 0.181675, 0.1826 , 0.183525, 0.18445 , 0.185375, 0.1863 , 0.187225, 0.18815 , 0.189075, 0.19 ]) - incident_beam()vector3m[ 0. 0. 150.]
Values:
array([ 0., 0., 150.]) - sample_position()vector3m[0. 0. 0.]
Values:
array([0., 0., 0.]) - source_position()vector3m[ 0. 0. -150.]
Values:
array([ 0., 0., -150.])
- (Q)float64counts2729.742, 4071.837, ..., 0.419, 0.045σ = 34.391, 47.398, ..., 0.109, 0.009
Values:
array([2.72974237e+03, 4.07183737e+03, 3.96718862e+03, 3.89124955e+03, 3.80164008e+03, 3.67807453e+03, 3.52326835e+03, 3.29514884e+03, 3.19940041e+03, 3.14971520e+03, 3.02506958e+03, 2.88396277e+03, 2.66118161e+03, 2.53163776e+03, 2.41394262e+03, 2.28977330e+03, 2.07685305e+03, 1.90423830e+03, 1.74687194e+03, 1.59168108e+03, 1.25564850e+03, 1.23361572e+03, 8.66285997e+02, 6.64304129e+02, 4.92014333e+02, 3.50413467e+02, 2.46102338e+02, 2.24153320e+02, 2.23885961e+02, 2.41489418e+02, 2.34410810e+02, 2.34401477e+02, 2.35054661e+02, 2.57658721e+02, 2.27001704e+02, 1.88015026e+02, 1.91104457e+02, 1.50309728e+02, 1.27540925e+02, 9.63903329e+01, 7.57636628e+01, 5.26868469e+01, 4.56785359e+01, 3.63682838e+01, 2.75738161e+01, 2.40292114e+01, 1.99115255e+01, 1.87975614e+01, 1.86958807e+01, 1.93381493e+01, 2.25731544e+01, 2.46014136e+01, 2.73478862e+01, 2.93031758e+01, 3.54386011e+01, 3.35298376e+01, 3.57868767e+01, 4.09468027e+01, 4.12233726e+01, 4.43668216e+01, 4.83627729e+01, 4.45983845e+01, 4.33080569e+01, 4.52745987e+01, 4.25102072e+01, 5.14532314e+01, 4.91291670e+01, 4.27051313e+01, 4.50136805e+01, 4.46079086e+01, 4.08642003e+01, 3.72661482e+01, 3.64436504e+01, 3.07974096e+01, 3.12425553e+01, 3.24481799e+01, 2.73734421e+01, 2.07840466e+01, 2.04611163e+01, 1.77629617e+01, 1.71598671e+01, 1.61730021e+01, 1.54056295e+01, 1.60936218e+01, 1.72087609e+01, 1.72829356e+01, 1.64599511e+01, 1.56396260e+01, 1.41352107e+01, 1.52486599e+01, 1.26459880e+01, 1.72002262e+01, 1.96248626e+01, 1.95014437e+01, 2.15019178e+01, 2.33989080e+01, 2.12985070e+01, 2.02094407e+01, 1.82456888e+01, 1.87728922e+01, 2.21676136e+01, 1.86479519e+01, 2.02860477e+01, 1.89767586e+01, 2.12063640e+01, 1.95735834e+01, 1.67284563e+01, 2.03220247e+01, 2.12473696e+01, 1.82170720e+01, 2.13471395e+01, 1.97899398e+01, 1.73949648e+01, 1.90921897e+01, 1.94319163e+01, 2.16560924e+01, 1.56146377e+01, 1.93097118e+01, 1.62392677e+01, 1.57373741e+01, 1.47462106e+01, 1.44770307e+01, 1.62958929e+01, 1.31343524e+01, 1.61244496e+01, 1.46280003e+01, 1.54331607e+01, 1.76933309e+01, 1.42260521e+01, 1.76359505e+01, 1.62185435e+01, 1.87482984e+01, 1.69934900e+01, 1.52698921e+01, 2.01045034e+01, 1.67727863e+01, 1.80520741e+01, 1.53005178e+01, 1.44254374e+01, 1.82446745e+01, 1.65682690e+01, 1.76288355e+01, 1.67338403e+01, 1.76189905e+01, 1.76716326e+01, 1.62512102e+01, 1.67895223e+01, 1.59882241e+01, 1.38324827e+01, 1.61281895e+01, 1.77625320e+01, 1.43177435e+01, 1.67516638e+01, 1.63389229e+01, 1.22747926e+01, 1.65744057e+01, 1.66453507e+01, 1.34394404e+01, 1.40480306e+01, 1.26103516e+01, 1.47370521e+01, 1.21776273e+01, 1.38911794e+01, 1.13118770e+01, 1.50950800e+01, 1.38275507e+01, 1.50275579e+01, 9.90839680e+00, 1.27541005e+01, 1.04657295e+01, 1.19202924e+01, 9.63832937e+00, 8.10519543e+00, 1.34445223e+01, 7.62032281e+00, 1.09081873e+01, 8.11793570e+00, 9.55968791e+00, 8.14524996e+00, 5.62046109e+00, 5.79273670e+00, 3.36388006e+00, 5.39154324e+00, 7.58935094e+00, 5.58888833e+00, 4.74662947e+00, 3.81061128e+00, 3.61654794e+00, 1.90361561e+00, 2.51216284e+00, 3.14619206e+00, 2.43321616e+00, 1.84364324e+00, 2.18131726e+00, 2.29937419e+00, 8.86200299e-01, 6.29927477e-01, 9.59958138e-01, 4.18974267e-01, 4.49784109e-02])
Variances (σ²):
array([1.18271398e+03, 2.24653215e+03, 2.46084166e+03, 2.79182223e+03, 3.09952887e+03, 3.31877065e+03, 3.51882590e+03, 3.59403563e+03, 3.75781306e+03, 4.04016715e+03, 4.11267226e+03, 4.18763665e+03, 4.02835918e+03, 4.05608684e+03, 3.97283204e+03, 3.89081401e+03, 3.63714227e+03, 3.31024572e+03, 3.06771829e+03, 2.83638514e+03, 2.21630998e+03, 2.21163413e+03, 1.52307222e+03, 1.18372863e+03, 8.42743550e+02, 5.54786047e+02, 3.78140024e+02, 3.03288752e+02, 2.73362684e+02, 2.75115324e+02, 2.32848446e+02, 2.15537958e+02, 2.02997760e+02, 2.21348223e+02, 1.65479271e+02, 1.18559698e+02, 1.07344519e+02, 7.25307374e+01, 5.53554268e+01, 3.48654614e+01, 2.20806521e+01, 1.12541900e+01, 7.31032941e+00, 5.20821442e+00, 2.51578299e+00, 1.59168074e+00, 1.01966399e+00, 8.82987846e-01, 8.91356117e-01, 9.76224321e-01, 1.50818201e+00, 2.16213326e+00, 2.77885994e+00, 3.52570526e+00, 4.94367841e+00, 5.15720149e+00, 6.08935046e+00, 8.12890686e+00, 8.78204707e+00, 1.03662293e+01, 1.22875058e+01, 1.11308471e+01, 1.12497290e+01, 1.24956310e+01, 1.13812596e+01, 1.49255128e+01, 1.38528178e+01, 1.17695279e+01, 1.19924762e+01, 1.17785174e+01, 1.05544479e+01, 8.51503502e+00, 8.07147524e+00, 6.59274761e+00, 6.17571123e+00, 5.69738777e+00, 4.36398533e+00, 2.54988992e+00, 2.36489865e+00, 1.86559300e+00, 1.59092941e+00, 1.36204807e+00, 1.23700995e+00, 1.18313671e+00, 1.41835544e+00, 1.38261825e+00, 1.26313591e+00, 1.25407807e+00, 1.10099065e+00, 1.29733502e+00, 9.61136179e-01, 1.80042379e+00, 2.43496597e+00, 2.28335302e+00, 3.05830193e+00, 3.67323058e+00, 3.26989597e+00, 2.89874215e+00, 2.58100203e+00, 2.80342317e+00, 4.24362124e+00, 3.22345334e+00, 3.37656574e+00, 3.35354269e+00, 4.20717560e+00, 3.60569547e+00, 2.68471570e+00, 3.81498121e+00, 3.78752077e+00, 2.96070362e+00, 3.82596399e+00, 3.53559968e+00, 2.73560388e+00, 3.49427464e+00, 3.37176452e+00, 3.51293740e+00, 1.97872010e+00, 2.98374734e+00, 2.29583807e+00, 2.12812835e+00, 1.87254291e+00, 1.87276497e+00, 2.50256119e+00, 1.64982894e+00, 2.16344780e+00, 1.90462291e+00, 2.18859465e+00, 2.86167717e+00, 1.97154177e+00, 2.86399908e+00, 2.84008017e+00, 3.88298704e+00, 3.19124591e+00, 2.63138049e+00, 4.45093976e+00, 3.01209448e+00, 3.89027915e+00, 2.90446887e+00, 2.29931033e+00, 3.81563643e+00, 3.16687774e+00, 3.94335436e+00, 3.79874552e+00, 3.68594159e+00, 3.80204361e+00, 3.61146024e+00, 3.87689978e+00, 3.29053836e+00, 2.50156703e+00, 3.63331258e+00, 4.07330062e+00, 2.73145030e+00, 3.64998974e+00, 3.37505994e+00, 2.35182951e+00, 3.76885476e+00, 3.59748223e+00, 2.42305683e+00, 2.91431476e+00, 2.35170548e+00, 3.02067399e+00, 2.39314553e+00, 3.42808108e+00, 2.09231475e+00, 3.33518745e+00, 3.86758277e+00, 4.08337887e+00, 1.90938956e+00, 3.57754955e+00, 2.79315012e+00, 3.54709219e+00, 2.77823483e+00, 1.90722948e+00, 4.70525479e+00, 1.99488574e+00, 3.92706755e+00, 2.18118845e+00, 3.57502354e+00, 2.76842468e+00, 1.68984068e+00, 1.46577780e+00, 1.90809285e-01, 1.43027543e+00, 2.63476367e+00, 1.88706709e+00, 1.62644365e+00, 1.24291962e+00, 8.03869571e-01, 3.15189630e-02, 4.63543706e-01, 1.32232211e+00, 5.06878141e-01, 5.33925402e-01, 6.59093547e-01, 8.92936421e-01, 1.73273164e-02, 1.14405438e-02, 3.31029083e-01, 1.17812501e-02, 7.99953070e-05])
Common errors#
In this section, we walk the reader through some of the most common errors that are encountered while working with sciline,
and try to bring extra explanations to the error messages, which are not always simple to understand.
UnsatisfiedRequirement#
This is probably the most common error you will encounter; and it typically means you have forgotten to set a parameter on the workflow.
If we go back to our original workflow where we still had the Foldername and QBins red boxes
workflow = sl.Pipeline(
# List the providers that make up the workflow.
(load, to_wavelength, to_Q, to_histogram),
)
and we immediately try to compute the final histogram
workflow.compute(QHistogram)
---------------------------------------------------------------------------
UnsatisfiedRequirement Traceback (most recent call last)
Cell In[13], line 1
----> 1 workflow.compute(QHistogram)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/pipeline.py:191, in Pipeline.compute(self, tp, reporter, **kwargs)
170 def compute(
171 self,
172 tp: type | Iterable[type] | "UnionType", # noqa: UP037 (needed by Sphinx)
173 reporter: Reporter | None = None,
174 **kwargs: Any,
175 ) -> Any:
176 """
177 Compute result for the given keys.
178
(...) 189 Keyword arguments passed to the ``.get()`` method.
190 """
--> 191 return self.get(tp, **kwargs).compute(reporter=reporter)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/pipeline.py:281, in Pipeline.get(self, keys, scheduler, handler, max_depth)
278 info = f'{e} Requested node not in graph. Did you mean one of: {nodes}?'
279 # Not raising `from e` because that includes noisy traceback of internals,
280 # which are not relevant to the user.
--> 281 raise type(e)(f'{info}\n\n') from None
282 return TaskGraph(
283 graph=graph,
284 targets=targets if multi else keys, # type: ignore[arg-type]
285 scheduler=scheduler,
286 )
UnsatisfiedRequirement: Missing input node 'Foldername'. Affects requested targets (via providers given in parentheses):
1. Foldername → (__main__.load) → RawData → (__main__.to_wavelength) → WavelengthData → (__main__.to_Q) → Qdata → (__main__.to_histogram) → QHistogram
we are told that a requirement Foldername is missing to be able to compute the result.
Sciline stops at the first missing requirement.
A missing provider#
We build the same workflow, be here we forget to add one of the provider functions at build time:
workflow = sl.Pipeline(
# Missing load provider!
(to_wavelength, to_Q, to_histogram),
)
# Set the parameters as before
workflow[QBins] = sc.linspace("Q", 5.0e-3, 0.19, 201, unit="1/angstrom")
workflow[Foldername] = utils.fetch_data("3-mcstas/SANS_with_sample_many_neutrons")
workflow[CoordTransformGraph] = graph
# The graph looks different
workflow.visualize(graph_attr={"rankdir": "LR"})
workflow.compute(QHistogram)
---------------------------------------------------------------------------
UnsatisfiedRequirement Traceback (most recent call last)
Cell In[15], line 1
----> 1 workflow.compute(QHistogram)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/pipeline.py:191, in Pipeline.compute(self, tp, reporter, **kwargs)
170 def compute(
171 self,
172 tp: type | Iterable[type] | "UnionType", # noqa: UP037 (needed by Sphinx)
173 reporter: Reporter | None = None,
174 **kwargs: Any,
175 ) -> Any:
176 """
177 Compute result for the given keys.
178
(...) 189 Keyword arguments passed to the ``.get()`` method.
190 """
--> 191 return self.get(tp, **kwargs).compute(reporter=reporter)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/pipeline.py:281, in Pipeline.get(self, keys, scheduler, handler, max_depth)
278 info = f'{e} Requested node not in graph. Did you mean one of: {nodes}?'
279 # Not raising `from e` because that includes noisy traceback of internals,
280 # which are not relevant to the user.
--> 281 raise type(e)(f'{info}\n\n') from None
282 return TaskGraph(
283 graph=graph,
284 targets=targets if multi else keys, # type: ignore[arg-type]
285 scheduler=scheduler,
286 )
UnsatisfiedRequirement: Missing input node 'RawData'. Affects requested targets (via providers given in parentheses):
1. RawData → (__main__.to_wavelength) → WavelengthData → (__main__.to_Q) → Qdata → (__main__.to_histogram) → QHistogram
We are now in a split state where the error message is telling it is missing the RawData.
The workflow is supposed to get the RawData from loading the data in the folder, but because provider function linking Foldername to RawData is missing,
the chain is broken and the Foldername is just an isolated box, not connected to any other parts of the graph.
Long error messages#
Sometimes, the error messages produced can appear dauntingly long.
A common example is when something goes wrong inside one of the provider functions.
The order in which the functions in the graph are called is managed/orchestrated by an external library called Dask, the calls happen deeply embedded in some scheduling mechanism that tries to optimize thread and memory use.
This means that when something fails inside one of the functions, the traceback will also contain a lot of Dask-specific information which users don’t actually need read or care about.
Instead, one should scroll all the way to the bottom to read CoordError: Coordinate 'q' not found.
def bad_to_histogram(events: QData, qbins: QBins) -> QHistogram:
"""Histogram data in Q bins"""
# Wrong coordinate name: it should be uppercase Q!
return events.hist(q=qbins)
workflow = sl.Pipeline(
(
load,
to_wavelength,
to_Q,
bad_to_histogram,
),
)
workflow[Foldername] = utils.fetch_data("3-mcstas/SANS_with_sample_many_neutrons")
workflow[CoordTransformGraph] = graph
workflow[QBins] = 200
# Uncomment the next line to see the exception
workflow.compute(QHistogram)
---------------------------------------------------------------------------
CoordError Traceback (most recent call last)
Cell In[16], line 21
17 workflow[CoordTransformGraph] = graph
18 workflow[QBins] = 200
19
20 # Uncomment the next line to see the exception
---> 21 workflow.compute(QHistogram)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/pipeline.py:191, in Pipeline.compute(self, tp, reporter, **kwargs)
170 def compute(
171 self,
172 tp: type | Iterable[type] | "UnionType", # noqa: UP037 (needed by Sphinx)
173 reporter: Reporter | None = None,
174 **kwargs: Any,
175 ) -> Any:
176 """
177 Compute result for the given keys.
178
(...) 189 Keyword arguments passed to the ``.get()`` method.
190 """
--> 191 return self.get(tp, **kwargs).compute(reporter=reporter)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/task_graph.py:122, in TaskGraph.compute(self, targets, reporter)
120 return dict(zip(targets, results, strict=True))
121 else:
--> 122 return self._scheduler.get(self._graph, [targets], reporter=reporter)[0]
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/scheduler.py:64, in NaiveScheduler.get(self, graph, keys, reporter)
62 with reporter.run_computation(graph.values()):
63 for t in tasks:
---> 64 results[t] = reporter.call_provider_with_reporting(graph[t], results)
65 return tuple(results[key] for key in keys)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/reporter.py:398, in NullReporter.call_provider_with_reporting(self, provider, values)
396 """Call a provider and report its progress with this reporter."""
397 # Override base method to avoid overhead.
--> 398 return provider.call(values)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/sciline/_provider.py:144, in Provider.call(self, values)
142 def call(self, values: dict[Hashable, Any]) -> Any:
143 """Call the provider with arguments extracted from ``values``."""
--> 144 return self._func(
145 *(values[arg] for arg in self._arg_spec.args),
146 **{key: values[arg] for key, arg in self._arg_spec.kwargs},
147 )
Cell In[16], line 4, in bad_to_histogram(events, qbins)
1 def bad_to_histogram(events: QData, qbins: QBins) -> QHistogram:
2 """Histogram data in Q bins"""
3 # Wrong coordinate name: it should be uppercase Q!
----> 4 return events.hist(q=qbins)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/scipp/core/data_group.py:755, in data_group_overload.<locals>.impl(data, *args, **kwargs)
753 if isinstance(data, DataGroup):
754 return data.apply(impl, *args, **kwargs) # type: ignore[arg-type]
--> 755 return func(data, *args, **kwargs)
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/scipp/core/binning.py:584, in hist(x, arg_dict, dim, **kwargs)
580 if isinstance(x, DataGroup):
581 # Only to make mypy happy because we have `DataGroup` in annotation of `x`
582 # so that Sphinx shows it.
583 raise TypeError("Internal error: input should not be a DataGroup")
--> 584 edges = _make_edges(x, arg_dict, kwargs)
585 erase = _find_replaced_dims(x, dims=edges, dim=dim)
586 if isinstance(x, Variable) and len(edges) != 1:
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/scipp/core/binning.py:385, in _make_edges(x, arg_dict, kwargs)
379 def _make_edges(
380 x: Variable | DataArray | Dataset,
381 arg_dict: IntoStrDict[SupportsIndex | Variable] | None,
382 kwargs: Mapping[str, SupportsIndex | Variable],
383 ) -> dict[str, Variable]:
384 return {
--> 385 name: _parse_coords_arg(x, name, arg)
386 for name, arg in combine_dict_args(arg_dict, kwargs).items()
387 }
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/scipp/core/binning.py:348, in _parse_coords_arg(x, name, arg)
346 if isinstance(arg, Variable) and name in arg.dims:
347 return arg
--> 348 coord = _get_coord(x, name)
349 start = coord.nanmin()
350 if (
351 not isinstance(x, Variable)
352 and (name in x.coords)
353 and x.coords.is_edges(name, name)
354 ):
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/scipp/core/binning.py:326, in _get_coord(x, name)
324 event_coord = x.bins.coords.get(name) if x.is_binned else None
325 coord = x.coords.get(name, event_coord)
--> 326 _require_coord(name, coord)
327 return coord
File ~/work/dmsc-school/dmsc-school/.pixi/envs/default/lib/python3.12/site-packages/scipp/core/binning.py:307, in _require_coord(name, coord)
305 def _require_coord(name: str, coord: object) -> None:
306 if coord is None:
--> 307 raise CoordError(f"Coordinate '{name}' not found.")
CoordError: Coordinate 'q' not found.
Generic domain types#
Sometimes we want to replicate parts of a workflow and apply it to a different input.
A typical case is when we have a sample measurement and want to correct it by a background measurement.
In that case many of the processing steps are identical, but ultimately we want to subtract the background measurement from the sample measurement.
Generic domain types lets us define domain types that represent “Y of the X” such as:
Filename[Background]: Filename of the background run.QHistogram[Sample]: The Q-histogram of the sample run.QHistogram[Background]: The Q-histogram of the background run.etc
from typing import TypeVar
# Define concrete RunType values we will use.
Sample = NewType("Sample", int)
Background = NewType("Background", int)
# Define generic domain types
RunType = TypeVar("RunType", Sample, Background)
# Domain types
# We use sciline.Scope to make Filename a "generic" domain type that depends on RunType.
class Foldername(sl.Scope[RunType, str], str): ...
class RawData(sl.Scope[RunType, sc.DataArray], sc.DataArray): ...
class WavelengthData(sl.Scope[RunType, sc.DataArray], sc.DataArray): ...
class QData(sl.Scope[RunType, sc.DataArray], sc.DataArray): ...
class QHistogram(sl.Scope[RunType, sc.DataArray], sc.DataArray): ...
FinalHistogram = NewType("FinalHistogram", sc.DataArray)
"""Data histogrammed in Q bins where background has been subtracted"""
# Note that the QBins and coordinate transform graph are the same for
# Sample and Background runs, so there is no need to make them into
# generic types.
CoordTransformGraph = NewType("CoordTransformGraph", dict)
QBins = NewType("QBins", sc.Variable)
def load(folder: Foldername[RunType]) -> RawData[RunType]:
"""Load raw data from file"""
return utils.load_sans(folder)
def to_wavelength(data: RawData[RunType], graph: CoordTransformGraph) -> WavelengthData[RunType]:
"""Compute wavelength for events"""
return data.transform_coords("wavelength", graph=graph)
def to_Q(data: WavelengthData[RunType], graph: CoordTransformGraph) -> QData[RunType]:
"""Compute Q for events"""
return data.transform_coords("Q", graph=graph)
def to_histogram(events: QData[RunType], qbins: QBins) -> QHistogram[RunType]:
"""Histogram data in Q bins"""
return events.hist(Q=qbins)
# A new function that will subtract background from sample run.
# Note here that instead of [RunType], we have [Sample] and [Background]
def subtract_background(
sample_data: QHistogram[Sample],
background_data:QHistogram[Background],
) -> FinalHistogram:
"""Subtract background signal"""
return sample_data - background_data
workflow = sl.Pipeline(
# List the providers that make up the workflow.
(load, to_wavelength, to_Q, to_histogram, subtract_background),
)
workflow.visualize(graph_attr={"rankdir": "LR"})
To set the parameter, we must not forget to also use the [Sample] and [Background] specifiers inside the square brackets:
workflow[Foldername[Sample]] = utils.fetch_data("3-mcstas/SANS_with_sample_many_neutrons")
workflow[Foldername[Background]] = utils.fetch_data("3-mcstas/SANS_without_sample_many_neutrons")
workflow[QBins] = sc.linspace("Q", 5.0e-3, 0.19, 201, unit="1/angstrom")
workflow[CoordTransformGraph] = graph
And we can finally compute the final result:
workflow.compute(FinalHistogram)
- Q: 200
- L1()float64m150.0
Values:
array(150.) - Q(Q [bin-edge])float641/Å0.005, 0.006, ..., 0.189, 0.19
Values:
array([0.005 , 0.005925, 0.00685 , 0.007775, 0.0087 , 0.009625, 0.01055 , 0.011475, 0.0124 , 0.013325, 0.01425 , 0.015175, 0.0161 , 0.017025, 0.01795 , 0.018875, 0.0198 , 0.020725, 0.02165 , 0.022575, 0.0235 , 0.024425, 0.02535 , 0.026275, 0.0272 , 0.028125, 0.02905 , 0.029975, 0.0309 , 0.031825, 0.03275 , 0.033675, 0.0346 , 0.035525, 0.03645 , 0.037375, 0.0383 , 0.039225, 0.04015 , 0.041075, 0.042 , 0.042925, 0.04385 , 0.044775, 0.0457 , 0.046625, 0.04755 , 0.048475, 0.0494 , 0.050325, 0.05125 , 0.052175, 0.0531 , 0.054025, 0.05495 , 0.055875, 0.0568 , 0.057725, 0.05865 , 0.059575, 0.0605 , 0.061425, 0.06235 , 0.063275, 0.0642 , 0.065125, 0.06605 , 0.066975, 0.0679 , 0.068825, 0.06975 , 0.070675, 0.0716 , 0.072525, 0.07345 , 0.074375, 0.0753 , 0.076225, 0.07715 , 0.078075, 0.079 , 0.079925, 0.08085 , 0.081775, 0.0827 , 0.083625, 0.08455 , 0.085475, 0.0864 , 0.087325, 0.08825 , 0.089175, 0.0901 , 0.091025, 0.09195 , 0.092875, 0.0938 , 0.094725, 0.09565 , 0.096575, 0.0975 , 0.098425, 0.09935 , 0.100275, 0.1012 , 0.102125, 0.10305 , 0.103975, 0.1049 , 0.105825, 0.10675 , 0.107675, 0.1086 , 0.109525, 0.11045 , 0.111375, 0.1123 , 0.113225, 0.11415 , 0.115075, 0.116 , 0.116925, 0.11785 , 0.118775, 0.1197 , 0.120625, 0.12155 , 0.122475, 0.1234 , 0.124325, 0.12525 , 0.126175, 0.1271 , 0.128025, 0.12895 , 0.129875, 0.1308 , 0.131725, 0.13265 , 0.133575, 0.1345 , 0.135425, 0.13635 , 0.137275, 0.1382 , 0.139125, 0.14005 , 0.140975, 0.1419 , 0.142825, 0.14375 , 0.144675, 0.1456 , 0.146525, 0.14745 , 0.148375, 0.1493 , 0.150225, 0.15115 , 0.152075, 0.153 , 0.153925, 0.15485 , 0.155775, 0.1567 , 0.157625, 0.15855 , 0.159475, 0.1604 , 0.161325, 0.16225 , 0.163175, 0.1641 , 0.165025, 0.16595 , 0.166875, 0.1678 , 0.168725, 0.16965 , 0.170575, 0.1715 , 0.172425, 0.17335 , 0.174275, 0.1752 , 0.176125, 0.17705 , 0.177975, 0.1789 , 0.179825, 0.18075 , 0.181675, 0.1826 , 0.183525, 0.18445 , 0.185375, 0.1863 , 0.187225, 0.18815 , 0.189075, 0.19 ]) - incident_beam()vector3m[ 0. 0. 150.]
Values:
array([ 0., 0., 150.]) - sample_position()vector3m[0. 0. 0.]
Values:
array([0., 0., 0.]) - source_position()vector3m[ 0. 0. -150.]
Values:
array([ 0., 0., -150.])
- (Q)float64counts2179.783, 3203.575, ..., -34.645, -14.410σ = 47.058, 59.236, ..., 5.464, 3.417
Values:
array([ 2.17978326e+03, 3.20357536e+03, 3.16684559e+03, 3.04100212e+03, 2.99980217e+03, 2.89457775e+03, 2.72061427e+03, 2.47046259e+03, 2.40372753e+03, 2.36911419e+03, 2.23863941e+03, 2.12065968e+03, 1.85292366e+03, 1.76566514e+03, 1.63776001e+03, 1.49430790e+03, 1.29575708e+03, 1.12131249e+03, 9.65495334e+02, 8.31224842e+02, 5.56028557e+02, 6.06823082e+02, 3.04530671e+02, 2.13361572e+02, 1.13783552e+02, 9.08442071e+01, -1.44610461e+00, 8.91542456e+00, -2.06785011e+01, -7.70222640e+01, -9.94011507e+01, -1.91805640e+02, -2.87132878e+02, -3.22643048e+02, -3.94928917e+02, -4.61650749e+02, -5.34910920e+02, -5.97503883e+02, -6.41407653e+02, -6.95457337e+02, -7.29475799e+02, -7.26274250e+02, -7.67330958e+02, -7.19061073e+02, -7.51742254e+02, -7.59506880e+02, -7.80300045e+02, -7.35323045e+02, -7.60405336e+02, -7.52632461e+02, -7.91963820e+02, -7.82679384e+02, -7.85853975e+02, -7.69571495e+02, -7.35977830e+02, -7.69139519e+02, -7.37588979e+02, -7.59016785e+02, -7.46021783e+02, -7.57872188e+02, -7.35702444e+02, -7.40001776e+02, -7.36364717e+02, -7.29779317e+02, -7.34746101e+02, -7.57719517e+02, -7.01653448e+02, -7.47614256e+02, -7.53301691e+02, -7.20829984e+02, -7.45690943e+02, -7.87627616e+02, -7.43486183e+02, -7.46216451e+02, -7.71483563e+02, -7.51959485e+02, -7.68664968e+02, -7.60437374e+02, -7.12475697e+02, -7.97040179e+02, -7.58465375e+02, -8.08592526e+02, -6.95754662e+02, -7.74850126e+02, -7.38402956e+02, -7.48771702e+02, -7.61269389e+02, -7.81988527e+02, -8.13773494e+02, -7.77495865e+02, -7.52496072e+02, -7.48674070e+02, -7.64357390e+02, -7.84962222e+02, -7.64974829e+02, -7.65429485e+02, -8.04089000e+02, -7.64014285e+02, -7.77148742e+02, -7.87622771e+02, -7.83208338e+02, -7.87498678e+02, -7.51231825e+02, -7.40553381e+02, -7.72953558e+02, -7.41638991e+02, -7.65108542e+02, -7.97540113e+02, -7.42382153e+02, -7.52065663e+02, -7.36252874e+02, -7.80531005e+02, -7.68632957e+02, -7.69802004e+02, -7.81524304e+02, -7.64294898e+02, -7.66284361e+02, -7.31939293e+02, -7.47823209e+02, -7.27604049e+02, -7.88201422e+02, -7.69882351e+02, -7.71572669e+02, -7.66765861e+02, -7.61159462e+02, -7.89017302e+02, -7.77910452e+02, -7.55701303e+02, -7.40434375e+02, -7.53155024e+02, -7.73672339e+02, -7.54622870e+02, -8.17646046e+02, -7.76555143e+02, -7.80587918e+02, -7.62338328e+02, -7.06584943e+02, -7.93455575e+02, -7.72719132e+02, -7.44303882e+02, -7.86206603e+02, -8.01519218e+02, -7.96588759e+02, -7.43780616e+02, -7.51159549e+02, -7.58375428e+02, -7.57112124e+02, -7.29678488e+02, -7.93804628e+02, -7.27546499e+02, -7.76141725e+02, -7.49101928e+02, -7.90904147e+02, -7.29726843e+02, -7.51887213e+02, -7.62059012e+02, -7.43814408e+02, -6.96142793e+02, -7.35497421e+02, -7.05353600e+02, -6.95276199e+02, -6.68287571e+02, -6.43470459e+02, -6.54074546e+02, -6.06127192e+02, -6.11194136e+02, -5.75620640e+02, -5.66053953e+02, -5.18602646e+02, -5.60286129e+02, -5.21552728e+02, -5.07695140e+02, -4.68263923e+02, -4.46670274e+02, -4.56326445e+02, -3.82821086e+02, -4.08547670e+02, -3.79838548e+02, -3.70682995e+02, -3.36854968e+02, -3.43590160e+02, -3.48997858e+02, -3.39841783e+02, -2.68685495e+02, -2.65219375e+02, -2.74412564e+02, -2.58029606e+02, -2.10156830e+02, -2.03291605e+02, -1.95493321e+02, -1.60746820e+02, -1.36250333e+02, -1.16553179e+02, -1.32615838e+02, -1.13972746e+02, -6.96261252e+01, -6.62443983e+01, -5.68736014e+01, -3.46450080e+01, -1.44101204e+01])
Variances (σ²):
array([2214.49555129, 3508.93862546, 3140.30880687, 3900.01483173, 3881.97973994, 3767.48138244, 3985.23227475, 4069.76570848, 4217.19283462, 4486.57732202, 4561.14973351, 4622.1033293 , 4497.74604833, 4485.73393247, 4420.54572851, 4356.98541574, 4092.61793252, 3759.20214402, 3524.22686142, 3283.15368583, 2636.14895492, 2588.55890883, 1880.14213534, 1477.41466801, 1092.50631088, 722.11254787, 531.34984115, 422.97555397, 399.09444594, 427.77829326, 385.03257713, 419.53964489, 470.12715952, 520.10561898, 500.07269478, 473.85383012, 508.13067674, 493.73430109, 493.25939439, 493.05634903, 486.13934592, 464.12012178, 480.56424408, 443.73774235, 445.28392398, 456.73422901, 455.16060577, 434.98492967, 454.68306467, 446.92780746, 474.85646785, 461.43632581, 471.87542762, 464.07914358, 452.22055122, 458.14137721, 455.19299279, 467.60646987, 455.39437048, 470.8842123 , 474.9919956 , 465.84601174, 462.23032419, 464.9253561 , 459.15397302, 491.89597004, 440.53483908, 464.0361537 , 476.24128746, 447.22094412, 468.89959071, 484.8382787 , 453.53105245, 450.21294135, 469.82189888, 461.86526167, 461.77298974, 449.15564971, 414.72478663, 472.8911635 , 442.30831985, 477.44582121, 401.84106973, 453.6468208 , 429.00158363, 435.87146144, 452.44772646, 461.97463803, 484.70718405, 453.07453836, 445.03526374, 441.07770402, 451.17609902, 471.2232774 , 452.26897558, 457.72213085, 483.13844403, 452.69314211, 459.30524674, 473.88171942, 464.05545173, 464.42398516, 452.43738442, 437.79297236, 460.92672457, 437.73380266, 462.98903994, 484.77974944, 444.55579606, 451.43372022, 443.25671489, 466.68363387, 451.19712289, 455.82391243, 471.89882466, 460.35884557, 443.87446874, 426.46799613, 442.00895401, 422.6999903 , 470.93828983, 458.59141454, 458.96997979, 452.51567551, 445.18880419, 466.67693904, 457.72874634, 444.48473209, 432.28303462, 452.7475167 , 456.67809837, 443.8764957 , 488.0758701 , 449.12557549, 469.94562899, 451.98852311, 419.6890858 , 473.32406731, 456.53621492, 434.5921049 , 466.88709894, 482.58731405, 476.63188834, 446.64148497, 441.72115244, 452.38441301, 443.13021169, 430.34044909, 472.50881333, 431.37688826, 468.4025103 , 439.9977598 , 477.1469382 , 429.77738191, 435.87957337, 454.2356065 , 453.0642163 , 419.83787595, 446.91013456, 433.95041386, 424.22206702, 412.7411867 , 404.03806833, 413.89718452, 388.92659461, 398.68811588, 383.82680469, 364.13701575, 347.53107306, 369.55792306, 358.41463718, 346.42937119, 318.93526879, 318.864909 , 317.34705 , 270.9520994 , 280.77103998, 276.49377697, 266.57905933, 244.24597746, 253.49379593, 251.8601296 , 257.84216445, 205.23351954, 203.71633138, 212.39227761, 200.27417645, 160.48709863, 156.69039985, 150.48597996, 127.02302871, 109.40907424, 92.5799693 , 111.84002756, 97.30513925, 56.49438967, 52.95180459, 49.8567188 , 29.85651861, 11.67683955])
To compute an intermediate result, we also need to use the [Sample] and [Background] specifiers:
workflow.compute(QData[Background])
- event: 5632505
- L1()float64m150.0
Values:
array(150.) - L2(event)float64m3.006, 3.011, ..., 3.001, 3.001
Values:
array([3.00597518, 3.01054061, 3.01034441, ..., 3.00079816, 3.00079919, 3.00076314], shape=(5632505,)) - Ltotal(event)float64m153.006, 153.011, ..., 153.001, 153.001
Values:
array([153.00597518, 153.01054061, 153.01034441, ..., 153.00079816, 153.00079919, 153.00076314], shape=(5632505,)) - Q(event)float641/Å0.070, 0.092, ..., 0.021, 0.021
Values:
array([0.07022426, 0.09226076, 0.09139858, ..., 0.0214054 , 0.02141427, 0.02092482], shape=(5632505,)) - incident_beam()vector3m[ 0. 0. 150.]
Values:
array([ 0., 0., 150.]) - position(event)vector3m[0. 0.18943806 3. ], [0. 0.25170377 3. ], ..., [0. 0.06925164 3. ], [0. 0.0676713 3. ]
Values:
array([[0. , 0.18943806, 3. ], [0. , 0.25170377, 3. ], [0. , 0.24934609, 3. ], ..., [0. , 0.06920702, 3. ], [0. , 0.06925164, 3. ], [0. , 0.0676713 , 3. ]], shape=(5632505, 3)) - sample_position()vector3m[0. 0. 0.]
Values:
array([0., 0., 0.]) - scattered_beam(event)vector3m[0. 0.18943806 3. ], [0. 0.25170377 3. ], ..., [0. 0.06925164 3. ], [0. 0.0676713 3. ]
Values:
array([[0. , 0.18943806, 3. ], [0. , 0.25170377, 3. ], [0. , 0.24934609, 3. ], ..., [0. , 0.06920702, 3. ], [0. , 0.06925164, 3. ], [0. , 0.0676713 , 3. ]], shape=(5632505, 3)) - source_position()vector3m[ 0. 0. -150.]
Values:
array([ 0., 0., -150.]) - tof(event)float64ms218.192, 220.419, ..., 261.898, 261.910
Values:
array([218.19202338, 220.41944362, 220.42506601, ..., 261.83788791, 261.89804922, 261.91011037], shape=(5632505,)) - two_theta(event)float64rad0.063, 0.084, ..., 0.023, 0.023
Values:
array([0.06306229, 0.08370521, 0.08292476, ..., 0.02306491, 0.02307978, 0.02255328], shape=(5632505,)) - wavelength(event)float64Å5.641, 5.699, ..., 6.772, 6.772
Values:
array([5.64144677, 5.69886761, 5.69902029, ..., 6.77015807, 6.77171357, 6.77202703], shape=(5632505,)) - x(event)float64m0.0, 0.0, ..., 0.0, 0.0
Values:
array([0., 0., 0., ..., 0., 0., 0.], shape=(5632505,)) - y(event)float64m0.189, 0.252, ..., 0.069, 0.068
Values:
array([0.18943806, 0.25170377, 0.24934609, ..., 0.06920702, 0.06925164, 0.0676713 ], shape=(5632505,))
- (event)float64counts0.532, 9.653e-06, ..., 1.020e-11, 8.301e-16σ = 0.532, 9.653e-06, ..., 1.020e-11, 8.301e-16
Values:
array([5.32442226e-01, 9.65296324e-06, 9.41361928e-10, ..., 1.25333928e-07, 1.01998359e-11, 8.30075727e-16], shape=(5632505,))
Variances (σ²):
array([2.83494724e-01, 9.31796994e-11, 8.86162279e-19, ..., 1.57085935e-14, 1.04036651e-22, 6.89025713e-31], shape=(5632505,))
How will Sciline be used at ESS?#
Most instruments will have one or more associated Sciline workflows.
The workflows will be the basic interface to the data reduction software.
On top of that interface we can build simpler but less flexible interfaces.
But that will take time.
In the early days after HC the interface to the data reduction will be mainly in the form of Sciline workflows.
What do I need to know?#
How to figure out what quantity to compute with the workflow.
Look at the workflow graph and read on the technique package documentation page.
How to figure out what parameters are needed to compute the target quantity.
Error messages tell you what is missing, or you can look at the workflow graph.
How to set parameters on the workflow.
How to compute the desired quantity.
How to read and understand common error messages.