HFIRSCDSubtractBackground v1#
Summary#
Subtract from WAND or DEMAND data in detector space a background measured at a single goniometer angle, scaled to the integrated flux of each goniometer angle of the sample.
See Also#
LoadWANDSCD, HB3AAdjustSampleNorm, HFIRGoniometerIndependentBackground, ConvertHFIRSCDtoMDE, MDNorm
Properties#
Name |
Direction |
Type |
Default |
Description |
|---|---|---|---|---|
InputWorkspace |
Input |
Mandatory |
Unnormalized sample in detector space, in counts. Either an MDHistoWorkspace with dimensions (y, x, goniometer angle), as returned by LoadWANDSCD or by HB3AAdjustSampleNorm with OutputType=’Detector’, or a WorkspaceGroup of such MDHistoWorkspaces, as returned by HB3AAdjustSampleNorm with OutputType=’Detector’ for several scans. Each member of a WorkspaceGroup is processed with its own flux logs. |
|
InputBackground |
Input |
Mandatory |
Background in counts, from the instrument of the sample: either an MDHistoWorkspace with dimensions (y, x, goniometer angle) and a single goniometer angle, or a Workspace2D with one value per spectrum, whose spectra are matched to the pixels of the sample through their detector IDs. |
|
InputGroupingWorkspace |
Input |
Optional: GroupingWorkspace for a sample whose pixels were grouped while the background’s were not, such as the OutputGroupingWorkspace of LoadWANDSCD or HB3AAdjustSampleNorm. The intensities of the background are summed within each group before the subtraction. To be used only with an ungrouped background: a grouped background is rejected when InputGroupingWorkspace is provided. |
||
NormalizedBy |
Input |
string |
None |
Flux used to scale the background to each goniometer angle of the sample: the monitor counts or the duration of each angle. With None, the background is subtracted unscaled. Allowed values: [‘None’, ‘Monitor’, ‘Time’] |
NullifyNegativeValues |
Input |
boolean |
True |
Set to zero the signal of bins that become negative after the subtraction. Their errors are unchanged. |
OutputWorkspace |
Output |
Mandatory |
Sample minus the scaled background. When it is the same workspace as InputWorkspace, the subtraction is done in place, member by member for a WorkspaceGroup. Otherwise, for a WorkspaceGroup, a new WorkspaceGroup with members named <OutputWorkspace>_<input member name>. |
|
OutputBackgroundWorkspace |
Output |
Optional: the background scaled to every goniometer angle of the sample. For a WorkspaceGroup sample, a WorkspaceGroup with members named <OutputBackgroundWorkspace>_<input member name>. |
Description#
This algorithm subtracts a background from WAND or DEMAND single crystal data in detector space.
The background is scaled to the integrated flux of each goniometer angle of the sample
before it is subtracted. The result, Sample - Background, can then be converted to Q-sample with
ConvertHFIRSCDtoMDE and normalized with MDNorm.
InputWorkspace is an MDHistoWorkspace with dimensions (y, x, goniometer angle), as returned by
LoadWANDSCD or by HB3AAdjustSampleNorm with
OutputType="Detector", or a WorkspaceGroup of such workspaces, such as the output of
HB3AAdjustSampleNorm with OutputType="Detector" for several scans. With this
output type, HB3AAdjustSampleNorm always returns several scans as a WorkspaceGroup.
Each member of a WorkspaceGroup is processed with its own flux logs.
The sample and the background must come from the same instrument.
Background#
InputBackground is in counts and takes one of two forms:
An MDHistoWorkspace with dimensions (y, x, goniometer angle) and a single goniometer angle, such as a background run loaded with LoadWANDSCD or HB3AAdjustSampleNorm. Without
InputGroupingWorkspace, it has the pixel dimensions of the sample.A Workspace2D with one value per spectrum, from the instrument of the sample. Its spectra are matched to the pixels of the sample through their detector IDs, using the
detectorIDsample log of the sample, which LoadWANDSCD and HB3AAdjustSampleNorm write. WithoutInputGroupingWorkspace, it has one spectrum per pixel of the sample. Its flux is read from its own sample logs, which hold a single value.
When the sample was loaded with pixel grouping (Grouping="2x2" or "4x4") and the background was not, provide
the GroupingWorkspace that the loader returns in OutputGroupingWorkspace as InputGroupingWorkspace. The
intensities and errors squared of the background are then summed within each group before the subtraction. The group
of each pixel or spectrum of the background is that of its detector ID, read from the detectorID log of an
MDHistoWorkspace background or from the spectra of a Workspace2D background.
For clarity, InputGroupingWorkspace is to be used only with an ungrouped background. The algorithm rejects a call
that passes both a grouped background and InputGroupingWorkspace, whatever the grouping of the background: the
same as that of the sample, finer, or coarser. When the sample and the background were loaded with the same grouping,
subtract them without InputGroupingWorkspace.
The sample must not be normalized, because the background is in counts. The algorithm does not check this; load the
sample with NormalizeData=False in LoadWANDSCD or
HB3AAdjustSampleNorm.
Scaling and subtraction#
For each pixel and each goniometer angle \(\theta\) of the sample, the output is
where \(S\) is the sample, \(B\) the background, and \(F_S(\theta)\) and \(F_B\) the integrated flux
of goniometer angle \(\theta\) of the sample and of the background. NormalizedBy selects the flux:
Monitor: the monitor counts, from themonitor_countlog for WAND and themonitorlog for DEMAND.Time: the duration, from thedurationlog for WAND and thetimelog for DEMAND.None: no scaling, \(r(\theta) = 1\).
The uncertainties are propagated as for any difference of independent measurements:
Negative values#
Where the sample contains only background, the subtraction can give a negative signal. When
NullifyNegativeValues is True (the default), the signal of such bins is set to zero and their errors keep the
propagated value \(\sigma_O\): the sample and the scaled background are two independent measurements of the same
background, and \(\sigma_O\) is the statistical uncertainty of their difference.
Output#
When OutputWorkspace is the same workspace as InputWorkspace, the subtraction is done in place and no copy of
the sample is made; for a WorkspaceGroup, each member is modified in place. Otherwise OutputWorkspace is a new
workspace and InputWorkspace is left unchanged; for a WorkspaceGroup, OutputWorkspace is a new WorkspaceGroup
whose members are named <OutputWorkspace>_<input member name>, as in
HB3AAdjustSampleNorm.
The optional OutputBackgroundWorkspace holds the background scaled to every goniometer angle of the sample,
\(r(\theta)\,B\), with errors \(r(\theta)\,\sigma_B\), and the dimensions and sample logs of the sample. For a
WorkspaceGroup sample, it is a WorkspaceGroup whose members are named <OutputBackgroundWorkspace>_<input member name>.
It is created only when a name is given.
A sample of several scans can occupy a lot of memory. Doing the subtraction in place and leaving
OutputBackgroundWorkspace empty avoids creating any workspace of the size of the sample. The members of a
WorkspaceGroup are processed one after the other, and the background is subtracted one goniometer angle at a time, so
the additional memory used is that of one copy of the signal of one member.
Workflow#
Load the sample in counts (
NormalizeData=False) with LoadWANDSCD or HB3AAdjustSampleNorm (OutputType="Detector"), with pixel grouping if wanted, and keep the GroupingWorkspace of a grouped sample (OutputGroupingWorkspace). For WAND, also keep the vanadium normalization (OutputNormalizationWorkspace).Load the background.
Convert
Sample - Backgroundand the normalization to Q-sample with ConvertHFIRSCDtoMDE, directly for WAND, or through HB3AAdjustSampleNorm withOutputType="Q-sample events"for DEMAND.Normalize with MDNorm, giving the converted normalization as
MonoSCDNormalizationWorkspace.
Usage#
The examples read data from the HFIR archive and are not run when the documentation is built.
Example - WAND, 4x4 grouped sample and ungrouped background
The background is the mean count rate of each pixel over the first 100 runs of the scan, in counts for the duration of the first run, with the flux logs of that run. An ungrouped WAND pixel records about 0.01 counts per run, so the median over the runs, as taken by HFIRGoniometerIndependentBackground, is zero. Unlike the median, the mean includes the Bragg peaks that cross a pixel during these runs. The sample is one run every 10 of the same 100 runs.
import numpy as np
from mantid.simpleapi import *
# Background: mean count rate of runs 26640-26739, ungrouped,
# in counts for the duration of the first run
runs = LoadWANDSCD(
IPTS=7776,
RunNumbers="26640-26739",
OutputWorkspace="background_runs"
)
SliceMDHisto(
InputWorkspace="background_runs",
Start="0,0,0",
End="512,3840,1",
OutputWorkspace="background_slice"
)
# SliceMDHisto shares the sample logs of its input,
# so the slice is cloned before its flux logs are changed
background = CloneMDWorkspace(
InputWorkspace="background_slice",
OutputWorkspace="background"
)
logs = runs.getExperimentInfo(0).run()
duration = np.asarray(logs.getProperty("duration").value)
scale = duration[0] / duration.sum()
counts = runs.getSignalArray().sum(axis=2, keepdims=True)
errors_squared = runs.getErrorSquaredArray().sum(axis=2, keepdims=True)
background.setSignalArray(scale * counts)
background.setErrorSquaredArray(scale**2 * errors_squared)
run = background.getExperimentInfo(0).mutableRun()
for log in ("duration", "monitor_count"):
run.addProperty(log, float(np.asarray(logs.getProperty(log).value)[0]), True)
DeleteWorkspaces(["background_runs", "background_slice"])
# Sample in counts, grouped 4x4, with the vanadium normalization and the GroupingWorkspace
LoadWANDSCD(
IPTS=7776,
RunNumbers=",".join(str(run) for run in range(26640, 26740, 10)),
VanadiumIPTS=7776,
VanadiumRunNumber=26509,
NormalizeData=False,
Grouping="4x4",
OutputWorkspace="sample",
OutputNormalizationWorkspace="norm",
OutputGroupingWorkspace="grouping"
)
# Subtract in place; the ungrouped background is grouped 4x4 by InputGroupingWorkspace
HFIRSCDSubtractBackground(
InputWorkspace="sample",
InputBackground="background",
InputGroupingWorkspace="grouping",
NormalizedBy="Time",
OutputWorkspace="sample"
)
# Convert to Q-sample and normalize; LoadWANDSCD has set the goniometer of each angle
for name in ("sample", "norm"):
ConvertHFIRSCDtoMDE(
InputWorkspace=name,
Wavelength=1.488,
OutputWorkspace=f"{name}_md"
)
# Horizontal plane, Q_sample_y between -0.5 and 0.5, over the Q range of these runs
MDNorm(
InputWorkspace="sample_md",
MonoSCDNormalizationWorkspace="norm_md",
RLU=False,
Dimension0Binning="0,0.05,5",
Dimension1Binning="-0.5,0.5",
Dimension2Binning="-7,0.05,1",
OutputWorkspace="result",
OutputDataWorkspace="result_data",
OutputNormalizationWorkspace="result_norm"
)
Example - DEMAND, WorkspaceGroup sample
Scans 0187 and 0188 of experiment 724, loaded together, are a WorkspaceGroup of two members, each with its own monitor counts. The background is the mean count rate per monitor count of each pixel over the 6 frames of scan 0188, which show no Bragg peak, in counts for the monitor of its first frame. As for WAND, a pixel records too few counts per frame for a median.
import numpy as np
from mantid.simpleapi import *
directory = "/HFIR/HB3A/IPTS-24655/shared/autoreduce"
# Background: mean count rate per monitor count of scan 0188, ungrouped,
# in counts for the monitor of its first frame
frames = HB3AAdjustSampleNorm(
Filename=f"{directory}/HB3A_exp0724_scan0188.nxs",
OutputType="Detector",
NormalizeData=False,
OutputWorkspace="background_frames"
)
SliceMDHisto(
InputWorkspace="background_frames",
Start="0,0,0",
End="1536,512,1",
OutputWorkspace="background_slice"
)
# SliceMDHisto shares the sample logs of its input,
# so the slice is cloned before its flux logs are changed
background = CloneMDWorkspace(
InputWorkspace="background_slice",
OutputWorkspace="background"
)
logs = frames.getExperimentInfo(0).run()
monitor = np.asarray(logs.getProperty("monitor").value)
scale = monitor[0] / monitor.sum()
counts = frames.getSignalArray().sum(axis=2, keepdims=True)
errors_squared = frames.getErrorSquaredArray().sum(axis=2, keepdims=True)
background.setSignalArray(scale * counts)
background.setErrorSquaredArray(scale**2 * errors_squared)
run = background.getExperimentInfo(0).mutableRun()
for log in ("time", "monitor"):
run.addProperty(log, float(np.asarray(logs.getProperty(log).value)[0]), True)
DeleteWorkspaces(["background_frames", "background_slice"])
sample_files = ",".join(f"{directory}/HB3A_exp0724_scan{scan:04d}.nxs" for scan in (187, 188))
HB3AAdjustSampleNorm(
Filename=sample_files,
OutputType="Detector",
NormalizeData=False,
OutputWorkspace="sample"
)
# Subtract in place, member by member
HFIRSCDSubtractBackground(
InputWorkspace="sample",
InputBackground="background",
NormalizedBy="Monitor",
OutputWorkspace="sample"
)
# Convert to Q-sample, merging the members, with the vanadium normalization
HB3AAdjustSampleNorm(
InputWorkspaces=",".join(mtd["sample"].getNames()),
VanadiumFile="/HFIR/HB3A/IPTS-24612/shared/autoreduce/HB3A_exp0722_scan0220.nxs",
NormalizeData=False,
OutputType="Q-sample events",
MergeInputs=True,
OutputWorkspace="sample_md",
OutputNormalizationWorkspace="norm_md"
)
# Q_sample_x between -1 and 1, over the Q range of these scans
MDNorm(
InputWorkspace="sample_md",
MonoSCDNormalizationWorkspace="norm_md",
RLU=False,
Dimension0Binning="-1,1",
Dimension1Binning="-4,0.05,1",
Dimension2Binning="-5,0.05,-2",
OutputWorkspace="result",
OutputDataWorkspace="result_data",
OutputNormalizationWorkspace="result_norm"
)
Categories: AlgorithmIndex | Diffraction\Reduction
Source#
Python: HFIRSCDSubtractBackground.py