GroupDetectors v2

../_images/GroupDetectors-v2_dlg.png

GroupDetectors dialog.

Summary

Sums spectra bin-by-bin, equivalent to grouping the data from a set of detectors. Individual groups can be specified by passing the algorithm a list of spectrum numbers, detector IDs or workspace indices. Many spectra groups can be created in one execution via an input file.

Properties

Name Direction Type Default Description
InputWorkspace Input MatrixWorkspace Mandatory The name of the input 2D workspace
OutputWorkspace Output MatrixWorkspace Mandatory The name of the output workspace
MapFile Input string   A file that consists of lists of spectra numbers to group. See the help for the file format. Allowed extensions: [‘.map’, ‘.xml’]
IgnoreGroupNumber Input boolean True If true, use sequential spectrum numbers, otherwise use the group number from MapFile as spectrum numbers.
GroupingPattern Input string   Describes how this algorithm should group the detectors. See the help for full instructions.
SpectraList Input int list   An array containing a list of the spectrum numbers to combine (DetectorList and WorkspaceIndexList are ignored if this is set)
DetectorList Input int list   An array of detector IDs to combine (WorkspaceIndexList is ignored if this is set)
WorkspaceIndexList Input unsigned int list   An array of workspace indices to combine
KeepUngroupedSpectra Input boolean False If true ungrouped spectra will be copied to the output workspace and placed after the groups
Behaviour Input string Sum Whether to sum or average the values when grouping detectors. Allowed values: [‘Sum’, ‘Average’]
PreserveEvents Input boolean True Keep the output workspace as an EventWorkspace, if the input has events.
CopyGroupingFromWorkspace Input MatrixWorkspace   The name of a workspace to copy the grouping from. This can be either a normal workspace or a grouping workspace, but they must be from the same instrument. Detector ids are used to match up the spectra to be grouped. If this option is selected all file and list options will be ignored.

Description

This algorithm sums, bin-by-bin, multiple spectra into a single spectra. The errors are summed in quadrature and the algorithm checks that the bin boundaries in X are the same. The new summed spectra are created at the start of the output workspace and have spectra numbers that start at zero and increase in the order the groups are specified. All detectors from the grouped spectra will be moved to belong to the new spectrum.

Not all spectra in the input workspace have to be copied to a group. If KeepUngroupedSpectra is set to true any spectra not listed will be copied to the output workspace after the groups in order. If KeepUngroupedSpectra is set to false only the spectra selected to be in a group will be used.

To create a single group the list of spectra can be identified using a list of either spectrum numbers, detector IDs or workspace indices. The list should be set against the appropriate property.

MapFile

An input file allows the specification of many groups. The file has the following format:

[number of groups in file]

[first group's number]
[number of spectra in first group]
[spectrum 1] [spectrum 2] [spectrum 3] [...] [spectrum n]

[second group's number]
[number of spectra in second group]
[spectrum 1] [spectrum 2] [spectrum 3] [...] [spectrum n]

[repeat as necessary]

Mantid will still work if the number of groups specified at the start is incorrect, but other software may not. Mantid will warn you if the value given is incorrect.

Each group’s spectrum number is determined by the group’s number. This behaviour can be overridden by enabling the IgnoreGroupNumber property, in which case the first group will be numbered 1, and the second 2, and so on.

Blank lines and whitespace in the map file are ignored. Comments may be entered using a #, like in a Python script.

An example of an input file follows:

2
1
64
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64
2
60
65 66 67 68 69 70 71 72 73 74
75 76 77 78 79 80 81 82 83 84
85 86 87 88 89 90 91 92 93 94
95 96 97 98 99 100 101 102 103 104
105 106 107 108 109 110 111 112 113 114
115 116 117 118 119 120 121 122 123 124

In addition the following XML grouping format is also supported

<?xml version="1.0" encoding="UTF-8" ?>
<detector-grouping>
  <group name="fwd1"> <ids val="1-32"/> </group>
  <group name="bwd1"> <ids val="33,36,38,60-64"/> </group>

  <group name="fwd2"><detids val="1,2,17,32"/></group>
  <group name="bwd2"><detids val="33,36,38,60,64"/> </group>
</detector-grouping>

where is used to specify spectra IDs and detector IDs.

GroupingPattern

Grouping can also be specified using the GroupingPattern property. Its syntax is as follows:

The pattern consists of a list of numbers that refer to workspace indices and various operators: ,:+-.

The spectra you wish to keep can be specified by selecting the appropriate workspace indices. This can be achieved with the following operators:

  • , allows you to specify additional indices. 1,2,4 will keep indices 1, 2 and 4 only.
  • : indicates a continuous range of indices. For example, 1:5 is the same as 1,2,3,4,5.
  • + sums two spectra together. 7+9 will produce a single spectra listing the sum of 7 and 9, ignoring any others.
  • - sums a range of spectra together. For example, 3-8 is the same as 3+4+5+6+7+8.

One could combine these operations, for example 10+12,13:89 would list the sum of 10 and 12 followed by 13 to 89.

Vertical Axis on Output

The OutputWorkspace of this algorithm will always have spectrum numbers as the vertical axis, independent of the vertical axis units in InputWorkspace. This is because after grouping, the vertical axis can have meaningless values and generally, there is not enough information available to rebuild the axis. The vertical axis can be manually restored afterwards by e.g. ConvertSpectrumAxis.

Previous Versions

Version 1

The set of spectra to be grouped can be given as a list of either spectrum numbers, detector IDs or workspace indices. The new, summed spectrum will appear in the workspace at the first workspace index of the pre-grouped spectra (which will be given by the ResultIndex property after execution). The detectors for all the grouped spectra will be moved to belong to the first spectrum. A technical note: the workspace indices previously occupied by summed spectra will have their data zeroed and their spectrum number set to a value of -1. See page for version 1 here.

Usage

Example 1: specifying a map file

import os

# Create a grouping file from the example above.
# It makes 2 groups of 64 and 60 detectors respectively.
groupingFileContent = \
"""
2
1
64
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64
2
60
65 66 67 68 69 70 71 72 73 74
75 76 77 78 79 80 81 82 83 84
85 86 87 88 89 90 91 92 93 94
95 96 97 98 99 100 101 102 103 104
105 106 107 108 109 110 111 112 113 114
115 116 117 118 119 120 121 122 123 124
"""
# Save the data to a file
groupingFilePath = os.path.expanduser('~/MantidUsageExample_GroupDetectorsGrouping.txt')
f = open(groupingFilePath, 'w')
f.write( groupingFileContent )
f.close()

# Create a workspace filled with a constant value = 0.3
ws=CreateSampleWorkspace()
# Group detectors according to the created file.
grouped = GroupDetectors( ws, MapFile = groupingFilePath )

# Check the result
print('Number of groups is {}'.format(grouped.getNumberHistograms()))
print('First grouped spectrum is a sum 64 input spectra:')
print('{:.1f} == 64 * 0.3 == {:.1f}'.format(grouped.readY(0)[0], 64 * 0.3))
print('Second grouped spectrum is a sum 60 input spectra:')
print('{:.1f} == 60 * 0.3 == {:.1f}'.format(grouped.readY(1)[0], 60 * 0.3))
# Get detector IDs of the first group
grp0_ids = grouped.getSpectrum(0).getDetectorIDs()
print('Number of grouped detectors is {}'.format(len(grp0_ids)))
print('5 first detectors in group: {}'.format([ grp0_ids[i] for i in range(5) ]))
print('5 last  detectors in group: {}'.format([ grp0_ids[i] for i in range(59,64)]))
# Get detector IDs of the second group
grp1_ids = grouped.getSpectrum(1).getDetectorIDs()
print('Number of grouped detectors is {}'.format(len(grp1_ids)))
print('5 first detectors in group: {}'.format([ grp1_ids[i] for i in range(5)]))
print('5 last  detectors in group: {}'.format([ grp1_ids[i] for i in range(55,60)]))

Output

Number of groups is 2
First grouped spectrum is a sum 64 input spectra:
19.2 == 64 * 0.3 == 19.2
Second grouped spectrum is a sum 60 input spectra:
18.0 == 60 * 0.3 == 18.0
Number of grouped detectors is 64
5 first detectors in group: [100, 101, 102, 103, 104]
5 last  detectors in group: [159, 160, 161, 162, 163]
Number of grouped detectors is 60
5 first detectors in group: [164, 165, 166, 167, 168]
5 last  detectors in group: [219, 220, 221, 222, 223]

Example 2: specifying spectrum numbers

# Create a workspace filled with a constant value = 0.3
ws=CreateSampleWorkspace()
# Group detectots using a list of spectrum numbers
grouped = GroupDetectors(ws,SpectraList=[1,3,5])

# Check the result
print('Number of groups is {}'.format(grouped.getNumberHistograms()))
print('The grouped spectrum is a sum 3 input spectra:')
print('{:.1f} == 3 * 0.3 == {:.1f}'.format(grouped.readY(0)[0], 3 * 0.3))

# Get detector IDs in the group
grp_ids = grouped.getSpectrum(0).getDetectorIDs()
print ('Number of grouped detectors is {}'.format(len(grp_ids)))
print ('Detector IDs: {}'.format(grp_ids))

Output

Number of groups is 1
The grouped spectrum is a sum 3 input spectra:
0.9 == 3 * 0.3 == 0.9
Number of grouped detectors is 3
Detector IDs: set(100,102,104)

Example 3: specifying detctor IDs

# Create a workspace filled with a constant value = 0.3
ws=CreateSampleWorkspace()
# Group detectots using a list of detctor IDs
grouped = GroupDetectors(ws,DetectorList=[100,102,104])

# Check the result
print('Number of groups is {}'.format(grouped.getNumberHistograms()))
print('The grouped spectrum is a sum 3 input spectra:')
print('{:.1f} == 3 * 0.3 == {:.1f}'.format(grouped.readY(0)[0], 3 * 0.3))

# Get detector IDs in the group
grp_ids = grouped.getSpectrum(0).getDetectorIDs()
print ('Number of grouped detectors is {}'.format(len(grp_ids)))
print ('Detector IDs: {}'.format(grp_ids))

Output

Number of groups is 1
The grouped spectrum is a sum 3 input spectra:
0.9 == 3 * 0.3 == 0.9
Number of grouped detectors is 3
Detector IDs: set(100,102,104)

Example 4: specifying workspace indices

# Create a workspace filled with a constant value = 0.3
ws=CreateSampleWorkspace()
# Group detectots using a list of workspace indices
grouped = GroupDetectors(ws,WorkspaceIndexList=[0,2,4])

# Check the result
print('Number of groups is {}'.format(grouped.getNumberHistograms()))
print('The grouped spectrum is a sum 3 input spectra:')
print('{:.1f} == 3 * 0.3 == {:.1f}'.format(grouped.readY(0)[0], 3 * 0.3))

# Get detector IDs in the group
grp_ids = grouped.getSpectrum(0).getDetectorIDs()
print ('Number of grouped detectors is {}'.format(len(grp_ids)))
print ('Detector IDs: {}'.format(grp_ids))

Output

Number of groups is 1
The grouped spectrum is a sum 3 input spectra:
0.9 == 3 * 0.3 == 0.9
Number of grouped detectors is 3
Detector IDs: set(100,102,104)

Example 5: keeping ungrouped spectra

import os

# Create a grouping file from the example above.
# It makes 2 groups of 64 and 60 detectors respectively.
groupingFileContent = \
"""
2
1
64
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64
2
60
65 66 67 68 69 70 71 72 73 74
75 76 77 78 79 80 81 82 83 84
85 86 87 88 89 90 91 92 93 94
95 96 97 98 99 100 101 102 103 104
105 106 107 108 109 110 111 112 113 114
115 116 117 118 119 120 121 122 123 124
"""
# Save the data to a file
groupingFilePath = os.path.expanduser('~/MantidUsageExample_GroupDetectorsGrouping.txt')
f = open(groupingFilePath, 'w')
f.write( groupingFileContent )
f.close()

# Create a workspace filled with a constant value = 0.3
ws=CreateSampleWorkspace()
# Group detectors according to the created file.
grouped = GroupDetectors( ws, MapFile=groupingFilePath, KeepUngroupedSpectra=True )

# Check the result
print('Number of spectra in grouped workspace is {}'.format(grouped.getNumberHistograms()))
print ('It includes 2 groups + {} remaining ungrouped spectra'.format(ws.getNumberHistograms() - (64 + 60)))

print('First  spectrum is grouped, it has {} detectors'.format(len(grouped.getSpectrum(0).getDetectorIDs())))
print('Second spectrum is grouped, it has {} detectors'.format(len(grouped.getSpectrum(1).getDetectorIDs())))
print('Spectrum   2  is ungrouped, it has  {} detector'.format(len(grouped.getSpectrum(2).getDetectorIDs())))
print('Spectrum   3  is ungrouped, it has  {} detector'.format(len(grouped.getSpectrum(3).getDetectorIDs())))
print('...')
print('Spectrum  77  is ungrouped, it has  {} detector'.format(len(grouped.getSpectrum(77).getDetectorIDs())))

Output

Number of spectra in grouped workspace is 78
It includes 2 groups + 76 remaining ungrouped spectra
First  spectrum is grouped, it has 64 detectors
Second spectrum is grouped, it has 60 detectors
Spectrum   2  is ungrouped, it has  1 detector
Spectrum   3  is ungrouped, it has  1 detector
...
Spectrum  77  is ungrouped, it has  1 detector

Example 6: Group detectors using spectra list

# Create test input
xx= range(0, 100, 10)
# create spectra with signal equal to spectra number
yy=[]
for i in range(1,11):
    yy=yy+[i for _ in range(10)]

ws=CreateWorkspace(DataX=xx,DataY=yy,NSpec=10);
# Group detectors
wsg0 = GroupDetectors(ws,SpectraList=[1,2,3],KeepUngroupedSpectra=True,Behaviour='Sum')
print("Grouped first 3 spectra results in workspace with {0} spectra and the grouped spectra is spectrum 0:".format(wsg0.getNumberHistograms()))
print(wsg0.dataY(0))
print("First unaffected spectrum is now spectrum 1, former spectrum 4:")
print(wsg0.dataY(1) )
print("*********************************************************")

# Group detectors differently
wsg1 = GroupDetectors(ws,SpectraList=[2,3,4],KeepUngroupedSpectra=True,Behaviour='Sum')
print("Grouped 3 spectra starting with second results in workspace with {0} spectra and the grouped spectra is spectrum 0:".format(wsg1.getNumberHistograms()))
print(wsg1.dataY(0))
print("First unaffected spectrum is now spectrum 1, former spectrum 0:")
print(wsg1.dataY(1))
print("*********************************************************")

# Group detectors in a chain:
wsg2 = GroupDetectors(wsg0,SpectraList=[4,5,6],KeepUngroupedSpectra=True,Behaviour='Sum')
print("Grouped 6 spectra 3x3 twice results in workspace with {0} spectra and the grouped spectra is spectrum 0 and 1:".format(wsg2.getNumberHistograms()))
print(wsg2.dataY(0))
print(wsg2.dataY(1))
print("First unaffected spectrum is now spectrum 3, former spectrum 7:")
print(wsg2.dataY(2))
print("*********************************************************")

Output:

Grouped first 3 spectra results in workspace with 8 spectra and the grouped spectra is spectrum 0:
[ 6.  6.  6.  6.  6.  6.  6.  6.  6.  6.]
First unaffected spectrum is now spectrum 1, former spectrum 4:
[ 4.  4.  4.  4.  4.  4.  4.  4.  4.  4.]
*********************************************************
Grouped 3 spectra starting with second results in workspace with 8 spectra and the grouped spectra is spectrum 0:
[ 9.  9.  9.  9.  9.  9.  9.  9.  9.  9.]
First unaffected spectrum is now spectrum 1, former spectrum 0:
[ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]
*********************************************************
Grouped 6 spectra 3x3 twice results in workspace with 6 spectra and the grouped spectra is spectrum 0 and 1:
[ 15.  15.  15.  15.  15.  15.  15.  15.  15.  15.]
[ 6.  6.  6.  6.  6.  6.  6.  6.  6.  6.]
First unaffected spectrum is now spectrum 3, former spectrum 7:
[ 7.  7.  7.  7.  7.  7.  7.  7.  7.  7.]
*********************************************************

Example 7: Group detectors using map file:

import os
# Create test input
xx= range(0, 100, 10)
# create spectra with signal equal to spectra number
yy=[]
for i in range(1,11):
    yy=yy+[i for _ in range(10)]

ws=CreateWorkspace(DataX=xx,DataY=yy,NSpec=10);

# Create map file
file_name = os.path.join(config["defaultsave.directory"], "TestMapFile.map")
f=open(file_name,'w');
f.write('4\n'); # header, four groups
f.write('1\n3\n'); # header group 1
f.write('1 2 3\n'); #  group 1
f.write('2\n3\n'); # header group 2
f.write('4 5 6\n'); #  group 2
f.write('3\n2\n'); # header group 3
f.write('7 8\n'); #  group 3
f.write('4\n2\n'); # header group 4
f.write('9 10\n'); #  group 4
f.close()

# Group detectors
wsg = GroupDetectors(ws,MapFile=file_name,KeepUngroupedSpectra=True,Behaviour='Sum')

print("Grouped workspace has {0} spectra".format(wsg.getNumberHistograms()))
print("spectrum 1 (sum of spectra 1-3): {}".format(wsg.dataY(0)))
print("spectrum 2 (sum of spectra 4-6): {}".format(wsg.dataY(1)))
print("spectrum 3 (sum of spectra 7-8): {}".format(wsg.dataY(2)))
print("spectrum 4 (sum of spectra 9-10): {}".format(wsg.dataY(3)))

Output:

Grouped workspace has 4 spectra
spectrum 1 (sum of spectra 1-3): [ 6.  6.  6.  6.  6.  6.  6.  6.  6.  6.]
spectrum 2 (sum of spectra 4-6): [ 15.  15.  15.  15.  15.  15.  15.  15.  15.  15.]
spectrum 3 (sum of spectra 7-8): [ 15.  15.  15.  15.  15.  15.  15.  15.  15.  15.]
spectrum 4 (sum of spectra 9-10): [ 19.  19.  19.  19.  19.  19.  19.  19.  19.  19.]

Example 8: Group detectors using grouping pattern:

# Create Workspace of 10 spectra each with one bin.
ws = CreateWorkspace(DataX=[1], DataY=[1,2,3,4,5,6,7,8,9,10], NSpec=10)

# Run algorithm adding first two spectra and then keep the fourth, add the fifth to seventh, and then keep the last three spectra
ws2 = GroupDetectors(ws, GroupingPattern="0+1,3,4-6,7:9")

#print result
print(ws2.readY(0))
print(ws2.readY(1))
print(ws2.readY(2))
print(ws2.readY(3))
print(ws2.readY(4))
print(ws2.readY(5))

Output:

[ 3.]
[ 4.]
[ 18.]
[ 8.]
[ 9.]
[ 10.]

Categories: Algorithm Index | Transforms\Grouping

Source

C++ source: GroupDetectors2.cpp (last modified: 2019-01-23)

C++ header: GroupDetectors2.h (last modified: 2018-10-31)