\(\renewcommand\AA{\unicode{x212B}}\)

NormaliseByDetector v1

../_images/ImageNotFound.png

Enable screenshots using DOCS_SCREENSHOTS in CMake

Summary

Normalise the input workspace by the detector efficiency.

See Also

Divide

Properties

Name

Direction

Type

Default

Description

InputWorkspace

Input

MatrixWorkspace

Mandatory

An input workspace in wavelength

OutputWorkspace

Output

MatrixWorkspace

Mandatory

An output workspace.

Description

This algorithm is designed to normalise a workspace via detector efficiency functions. For this algorithm to work, the Instrument Definition File (IDF) must have fitting functions on the component tree. The setup information for this, as well as some examples, are provided below.

At a high-level, the algorithm does this:

  1. Extract a detector efficiency function \(e = f(\lambda)\)

  2. Using the bin boundaries on the input workspace, calculate efficiency Y and E values and generate a new workspace from the results

  3. Divide the input workspace by the efficiency workspace

Prerequisites

The Input Workspace

  1. The input workspace must be a MatrixWorkspace

  2. The input workspace must have X-units of Wavelength, run ConvertUnits v1 on your input workspace if it is not already in Wavelength.

  3. The input workspace must be a histogram workspace run ConvertToHistogram v1 on your input workspace if it is not already histogrammed.

The Instrument Definition File

Background

In brief, the components in the IDF file form a tree structure. Detectors and Instruments are both types of component. Detectors are ultimately children of Instruments in the tree structure. For a more complete description see IDF. The tree structure of the components, mean that fitting functions do not necessarily have to be assigned on a detector-by-detector basis. Applying a fit function to the instrument, will ensure that all subcomponents (including detectors), pick-up that function. However, functions assigned to lower-level components (such as detectors) take precedence over and existing functions that might exist on parent components (such as the instrument). You can even, have some parameters for a function provided against the detector, and pick up defaults from the bank, or instrument if they have been specified there.

Examples

Applying a LinearFunction to the whole instrument, hard-coded with A1=2 and A0=1. Fictional instrument is called basic_rect.

<parameter-file instrument = "basic_rect" date = "2012-01-31T00:00:00">
  <component-link name="basic_rect">
  <parameter name="LinearBackground:A0" type="fitting">
    <formula eq="1" result-unit="Wavelength"/>
    <fixed />
  </parameter>
  <parameter name="LinearBackground:A1" type="fitting">
    <formula eq="2" result-unit="Wavelength"/>
    <fixed />
  </parameter>
  </component-link>
</parameter-file>

Applying the same LinearFunction to two different detectors, with different coefficients is shown below:

<parameter-file instrument = "basic_rect" date = "2012-01-31T00:00:00">
<component-link name="bank1(0,0)">
   <parameter name="LinearBackground:A0" type="fitting">
       <formula eq="0" result-unit="Wavelength"/>
       <fixed />
   </parameter>
   <parameter name="LinearBackground:A1" type="fitting">
       <formula eq="1" result-unit="Wavelength"/>
       <fixed />
   </parameter>
</component-link>
<component-link name="bank2(0,0)">
   <parameter name="LinearBackground:A0" type="fitting">
       <formula eq="1" result-unit="Wavelength"/>
       <fixed />
   </parameter>
   <parameter name="LinearBackground:A1" type="fitting">
       <formula eq="1" result-unit="Wavelength"/>
       <fixed />
   </parameter>
</component-link>
</parameter-file>

In the following the LinearFunction A0 coefficient is set globally for all detectors at the instrument level, while the A1 coefficient is provided for each detector. In this way the Algorithm sees a complete definition for the Linear function (both A1 and A0) from two incomplete definitions on different components in the tree.

<parameter-file instrument = "basic_rect" date = "2012-01-31T00:00:00">
<component-link name="basic_rect">
<parameter name="LinearBackground:A0" type="fitting">
   <formula eq="3" result-unit="Wavelength"/>
   <fixed />
</parameter>
</component-link>
<component-link name="bank1(0,0)">
<parameter name="LinearBackground:A1" type="fitting">
   <formula eq="0" result-unit="Wavelength"/>
   <fixed />
</parameter>
</component-link>
<component-link name="bank2(0,0)">
<parameter name="LinearBackground:A1" type="fitting">
   <formula eq="1" result-unit="Wavelength"/>
   <fixed />
</parameter>
</component-link>
</parameter-file>

Usage

Example - A simple linear correction

import os

#create a param file
param_text = '''<parameter-file instrument = "basic_rect" date = "2012-01-31T00:00:00">
      <component-link name="basic_rect">
      <parameter name="LinearBackground:A0" type="fitting">
        <formula eq="1" result-unit="Wavelength"/>
        <fixed />
      </parameter>
      <parameter name="LinearBackground:A1" type="fitting">
        <formula eq="2" result-unit="Wavelength"/>
        <fixed />
      </parameter>
      </component-link>
    </parameter-file>'''

#find a suitable directory to save the param file
param_dir = config["defaultsave.directory"]
if not os.path.isdir(param_dir):
  #use the users home directory if default save is not set
  param_dir = os.path.expanduser('~')
param_file_path = os.path.join(param_dir,"NormByDet_Ex_param.xml")
#write the param file out
with open(param_file_path, "w") as param_file:
  param_file.write(param_text)


# a sample workspace with a sample instrument
ws = CreateSampleWorkspace()
# convert to Wavelength
ws = ConvertUnits(ws,"Wavelength")
#Load the param file into the workspace
LoadParameterFile(ws,param_file_path)

#Now we are ready to run the correction
wsCorrected = NormaliseByDetector(ws)

print("The correction will divide the data by an increasing linear function.")
print("f(x) = 2x + 1")
for i in range(0,wsCorrected.blocksize(),10):
  print("The correct value in bin {} is {:.2f} compared to {:.2f}".format(i,wsCorrected.readY(0)[i],ws.readY(0)[i]))

#clean up the file
if os.path.exists(param_file_path):
  os.remove(param_file_path)

Output:

The correction will divide the data by an increasing linear function.
f(x) = 2x + 1
The correct value in bin 0 is 0.28 compared to 0.30
The correct value in bin 10 is 0.14 compared to 0.30
The correct value in bin 20 is 0.09 compared to 0.30
The correct value in bin 30 is 0.07 compared to 0.30
The correct value in bin 40 is 0.06 compared to 0.30
The correct value in bin 50 is 1.63 compared to 10.30
The correct value in bin 60 is 0.04 compared to 0.30
The correct value in bin 70 is 0.04 compared to 0.30
The correct value in bin 80 is 0.03 compared to 0.30
The correct value in bin 90 is 0.03 compared to 0.30

Categories: AlgorithmIndex | CorrectionFunctions\NormalisationCorrections

Source

C++ header: NormaliseByDetector.h

C++ source: NormaliseByDetector.cpp