Skip to content

Commit 09ac6bb

Browse files
andy-bridgerpeterfpeterson
authored andcommitted
Add optional IncludeDetectorPosition to CreateDetectorTable (#38960)
* optional add position flag for detector table * updated new parameter declaration * added detector position to exception handling * updated the docstring of createDetectorTableWorkspace * added release note * disable include position option for peaks ws * added test coverage for the no detector exceptions * add semicolons to endo of assert statements * check table population isn't just null values
1 parent ab54b0c commit 09ac6bb

File tree

4 files changed

+153
-27
lines changed

4 files changed

+153
-27
lines changed

Framework/Algorithms/inc/MantidAlgorithms/CreateDetectorTable.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class MANTID_ALGORITHMS_DLL CreateDetectorTable final : public API::Algorithm {
5454
/// Creates table workspace of detector information from a given workspace
5555
API::ITableWorkspace_sptr createDetectorTableWorkspace(const API::MatrixWorkspace_sptr &ws,
5656
const std::vector<int> &indices, const bool includeData,
57-
Kernel::Logger &logger);
57+
const bool includeDetectorPosition, Kernel::Logger &logger);
5858

5959
/// Converts a list to a string, shortened if necessary
6060
std::string createTruncatedList(const std::set<int> &elements);
@@ -63,9 +63,11 @@ void populateTable(Mantid::API::ITableWorkspace_sptr &t, const Mantid::API::Matr
6363
const std::vector<int> &indices, const Mantid::API::SpectrumInfo &spectrumInfo,
6464
bool signedThetaParamRetrieved, bool showSignedTwoTheta,
6565
const Mantid::Geometry::PointingAlong &beamAxisIndex, const double sampleDist, const bool isScanning,
66-
const bool include_data, const bool calcQ, const bool includeDiffConstants, Kernel::Logger &logger);
66+
const bool include_data, const bool calcQ, const bool includeDiffConstants,
67+
const bool includeDetectorPosition, Kernel::Logger &logger);
6768
std::vector<std::pair<std::string, std::string>> createColumns(const bool isScanning, const bool includeData,
68-
const bool calcQ, const bool hasDiffConstants);
69+
const bool calcQ, const bool hasDiffConstants,
70+
const bool includeDetectorPosition);
6971

7072
} // namespace Algorithms
7173
} // namespace Mantid

Framework/Algorithms/src/CreateDetectorTable.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ void CreateDetectorTable::init() {
2727
declareProperty("IncludeData", false, "Include the first value from each spectrum.");
2828
setPropertySettings("IncludeData",
2929
std::make_unique<EnabledWhenWorkspaceIsType<MatrixWorkspace>>("InputWorkspace", true));
30-
30+
declareProperty<bool>("IncludeDetectorPosition", false,
31+
"Include the absolute position of the detector group for each spectrum.", Direction::Input);
32+
setPropertySettings("IncludeDetectorPosition",
33+
std::make_unique<EnabledWhenWorkspaceIsType<MatrixWorkspace>>("InputWorkspace", true));
3134
declareProperty(std::make_unique<WorkspaceProperty<TableWorkspace>>("DetectorTableWorkspace", "", Direction::Output,
3235
PropertyMode::Optional),
3336
"The name of the outputted detector table workspace, if left empty then "
@@ -38,6 +41,7 @@ void CreateDetectorTable::exec() {
3841
Workspace_sptr inputWS = getProperty("InputWorkspace");
3942
bool includeData = getProperty("IncludeData");
4043
std::vector<int> indices = getProperty("WorkspaceIndices");
44+
bool includeDetectorPosition = getProperty("IncludeDetectorPosition");
4145

4246
ITableWorkspace_sptr detectorTable;
4347

@@ -46,7 +50,7 @@ void CreateDetectorTable::exec() {
4650
if (sample == nullptr) {
4751
throw std::runtime_error("Matrix workspace has no instrument information");
4852
}
49-
detectorTable = createDetectorTableWorkspace(matrix, indices, includeData, g_log);
53+
detectorTable = createDetectorTableWorkspace(matrix, indices, includeData, includeDetectorPosition, g_log);
5054

5155
if (detectorTable == nullptr) {
5256
throw std::runtime_error("Unknown error while creating detector table for matrix workspace");
@@ -98,12 +102,15 @@ std::map<std::string, std::string> CreateDetectorTable::validateInputs() {
98102
* @param indices :: Limit the table to these workspace indices
99103
* @param includeData :: If true then first value from the each spectrum is
100104
* displayed
105+
* @param includeDetectorPosition :: If true then include the absolute position of
106+
* the detector group for each spectrum
101107
* @param logger: The Mantid logger so errors can be written to it.
102108
*
103109
* @return A pointer to the table workspace of detector information
104110
*/
105111
ITableWorkspace_sptr createDetectorTableWorkspace(const MatrixWorkspace_sptr &ws, const std::vector<int> &indices,
106-
const bool includeData, Logger &logger) {
112+
const bool includeData, const bool includeDetectorPosition,
113+
Logger &logger) {
107114
IComponent_const_sptr sample = ws->getInstrument()->getSample();
108115

109116
// check if efixed value is available
@@ -134,7 +141,7 @@ ITableWorkspace_sptr createDetectorTableWorkspace(const MatrixWorkspace_sptr &ws
134141
}
135142

136143
// Prepare column names
137-
auto colNames = createColumns(isScanning, includeData, calcQ, hasDiffConstants);
144+
auto colNames = createColumns(isScanning, includeData, calcQ, hasDiffConstants, includeDetectorPosition);
138145

139146
const int ncols = static_cast<int>(colNames.size());
140147
const int nrows = indices.empty() ? static_cast<int>(ws->getNumberHistograms()) : static_cast<int>(indices.size());
@@ -156,13 +163,14 @@ ITableWorkspace_sptr createDetectorTableWorkspace(const MatrixWorkspace_sptr &ws
156163
// value should be displayed
157164

158165
populateTable(t, ws, nrows, indices, spectrumInfo, signedThetaParamRetrieved, showSignedTwoTheta, beamAxisIndex,
159-
sampleDist, isScanning, includeData, calcQ, hasDiffConstants, logger);
166+
sampleDist, isScanning, includeData, calcQ, hasDiffConstants, includeDetectorPosition, logger);
160167

161168
return t;
162169
}
163170

164171
std::vector<std::pair<std::string, std::string>> createColumns(const bool isScanning, const bool includeData,
165-
const bool calcQ, const bool hasDiffConstants) {
172+
const bool calcQ, const bool hasDiffConstants,
173+
const bool includeDetectorPosition) {
166174
std::vector<std::pair<std::string, std::string>> colNames;
167175
colNames.emplace_back("double", "Index");
168176
colNames.emplace_back("int", "Spectrum No");
@@ -187,14 +195,17 @@ std::vector<std::pair<std::string, std::string>> createColumns(const bool isScan
187195
colNames.emplace_back("double", "DIFC - Uncalibrated");
188196
colNames.emplace_back("double", "TZERO");
189197
}
198+
if (includeDetectorPosition) {
199+
colNames.emplace_back("V3D", "Position");
200+
}
190201
return colNames;
191202
}
192203

193204
void populateTable(ITableWorkspace_sptr &t, const MatrixWorkspace_sptr &ws, const int nrows,
194205
const std::vector<int> &indices, const SpectrumInfo &spectrumInfo, bool signedThetaParamRetrieved,
195206
bool showSignedTwoTheta, const PointingAlong &beamAxisIndex, const double sampleDist,
196207
const bool isScanning, const bool includeData, const bool calcQ, const bool includeDiffConstants,
197-
Logger &logger) {
208+
const bool includeDetectorPosition, Logger &logger) {
198209
PARALLEL_FOR_IF(Mantid::Kernel::threadSafe(*ws))
199210
for (int row = 0; row < nrows; ++row) {
200211
TableRow colValues = t->getRow(row);
@@ -299,6 +310,10 @@ void populateTable(ITableWorkspace_sptr &t, const MatrixWorkspace_sptr &ws, cons
299310
<< diffConsts[UnitParams::tzero];
300311
}
301312
}
313+
if (includeDetectorPosition) {
314+
const auto &detectorPosition = spectrumInfo.position(wsIndex);
315+
colValues << detectorPosition;
316+
}
302317
} catch (const std::exception &) {
303318
colValues.row(row);
304319
colValues << static_cast<double>(wsIndex);
@@ -317,6 +332,9 @@ void populateTable(ITableWorkspace_sptr &t, const MatrixWorkspace_sptr &ws, cons
317332
if (includeDiffConstants) {
318333
colValues << 0.0 << 0.0 << 0.0 << 0.0;
319334
}
335+
if (includeDetectorPosition) {
336+
colValues << V3D(0.0, 0.0, 0.0);
337+
}
320338
} // End catch for no spectrum
321339
}
322340
}

Framework/Algorithms/test/CreateDetectorTableTest.h

Lines changed: 122 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
4141
TS_ASSERT(alg.isInitialized());
4242

4343
const auto &props = alg.getProperties();
44-
TS_ASSERT_EQUALS(props.size(), 4);
44+
TS_ASSERT_EQUALS(props.size(), 5);
4545

4646
TS_ASSERT_EQUALS(props[0]->name(), "InputWorkspace");
4747
TS_ASSERT(props[0]->isDefault());
@@ -52,17 +52,20 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
5252
TS_ASSERT_EQUALS(props[2]->name(), "IncludeData");
5353
TS_ASSERT(props[2]->isDefault());
5454

55-
TS_ASSERT_EQUALS(props[3]->name(), "DetectorTableWorkspace");
55+
TS_ASSERT_EQUALS(props[3]->name(), "IncludeDetectorPosition");
5656
TS_ASSERT(props[3]->isDefault());
57-
TS_ASSERT(dynamic_cast<WorkspaceProperty<TableWorkspace> *>(props[3]));
57+
58+
TS_ASSERT_EQUALS(props[4]->name(), "DetectorTableWorkspace");
59+
TS_ASSERT(props[4]->isDefault());
60+
TS_ASSERT(dynamic_cast<WorkspaceProperty<TableWorkspace> *>(props[4]));
5861
}
5962

6063
void test_Exec_Matrix_Workspace() {
6164
Workspace2D_sptr inputWS = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(2, 10);
6265

6366
CreateDetectorTable alg;
64-
TS_ASSERT_THROWS_NOTHING(alg.initialize())
65-
TS_ASSERT(alg.isInitialized())
67+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
68+
TS_ASSERT(alg.isInitialized());
6669
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(inputWS)));
6770
TS_ASSERT_THROWS_NOTHING(alg.execute();)
6871
TS_ASSERT(alg.isExecuted());
@@ -81,6 +84,39 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
8184
// Check the results
8285
TS_ASSERT_EQUALS(ws->columnCount(), 11);
8386
TS_ASSERT_EQUALS(ws->rowCount(), 2);
87+
TS_ASSERT_EQUALS(ws->cell<int>(0, 1), 1); // Spectrum No should be 1, if not in the exception
88+
89+
// Remove workspace from the data service.
90+
AnalysisDataService::Instance().remove(ws->getName());
91+
}
92+
93+
void test_Exec_Matrix_Workspace_with_no_valid_spectra() {
94+
Workspace2D_sptr inputWS = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(1, 10);
95+
auto &spec = inputWS->getSpectrum(0);
96+
spec.clearDetectorIDs(); // clear the detectors to test the exception catching
97+
98+
CreateDetectorTable alg;
99+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
100+
TS_ASSERT(alg.isInitialized());
101+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(inputWS)));
102+
TS_ASSERT_THROWS_NOTHING(alg.execute();)
103+
TS_ASSERT(alg.isExecuted());
104+
105+
// Not setting an output workspace name should give the name:
106+
//[input workspace name] + "-Detectors"
107+
TableWorkspace_sptr ws;
108+
TS_ASSERT_THROWS_NOTHING(
109+
ws = AnalysisDataService::Instance().retrieveWS<TableWorkspace>(inputWS->getName() + "-Detectors"));
110+
TS_ASSERT(ws);
111+
112+
if (!ws) {
113+
return;
114+
}
115+
116+
// Check the results
117+
TS_ASSERT_EQUALS(ws->columnCount(), 11);
118+
TS_ASSERT_EQUALS(ws->rowCount(), 1);
119+
TS_ASSERT_EQUALS(ws->cell<int>(0, 1), -1); // Spectrum No should be -1
84120

85121
// Remove workspace from the data service.
86122
AnalysisDataService::Instance().remove(ws->getName());
@@ -91,8 +127,8 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
91127
std::string outWSName{"Detector Table Test"};
92128

93129
CreateDetectorTable alg;
94-
TS_ASSERT_THROWS_NOTHING(alg.initialize())
95-
TS_ASSERT(alg.isInitialized())
130+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
131+
TS_ASSERT(alg.isInitialized());
96132
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(inputWS)));
97133
TS_ASSERT_THROWS_NOTHING(alg.setProperty("WorkspaceIndices", "1"));
98134
TS_ASSERT_THROWS_NOTHING(alg.setProperty("IncludeData", true));
@@ -122,6 +158,7 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
122158
// Check the results
123159
TS_ASSERT_EQUALS(ws->columnCount(), 13);
124160
TS_ASSERT_EQUALS(ws->rowCount(), 1);
161+
TS_ASSERT_EQUALS(ws->cell<int>(0, 1), 2); // Spectrum No should be 2 due to the WorkspaceIndex
125162

126163
// Remove workspace from the data service.
127164
AnalysisDataService::Instance().remove(outWSName);
@@ -131,11 +168,11 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
131168
PeaksWorkspace_sptr inputWS = WorkspaceCreationHelper::createPeaksWorkspace(5, false);
132169

133170
CreateDetectorTable alg;
134-
TS_ASSERT_THROWS_NOTHING(alg.initialize())
135-
TS_ASSERT(alg.isInitialized())
136-
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", inputWS))
137-
TS_ASSERT_THROWS_NOTHING(alg.execute())
138-
TS_ASSERT(alg.isExecuted())
171+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
172+
TS_ASSERT(alg.isInitialized());
173+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", inputWS));
174+
TS_ASSERT_THROWS_NOTHING(alg.execute());
175+
TS_ASSERT(alg.isExecuted());
139176

140177
TableWorkspace_sptr ws;
141178
TS_ASSERT_THROWS_NOTHING(
@@ -147,8 +184,9 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
147184
}
148185

149186
// Check the results
150-
TS_ASSERT_EQUALS(ws->columnCount(), 2)
151-
TS_ASSERT_EQUALS(ws->rowCount(), 5)
187+
TS_ASSERT_EQUALS(ws->columnCount(), 2);
188+
TS_ASSERT_EQUALS(ws->rowCount(), 5);
189+
TS_ASSERT_EQUALS(ws->cell<int>(0, 1), 0); // First column is Index when exec on PeaksWorkspace, so expect 0
152190

153191
// Remove workspace from the data service.
154192
AnalysisDataService::Instance().remove(ws->getName());
@@ -158,12 +196,79 @@ class CreateDetectorTableTest : public CxxTest::TestSuite {
158196
ITableWorkspace_sptr inputWS = std::make_shared<TableWorkspace>();
159197

160198
CreateDetectorTable alg;
161-
TS_ASSERT_THROWS_NOTHING(alg.initialize())
162-
TS_ASSERT(alg.isInitialized())
163-
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", inputWS))
199+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
200+
TS_ASSERT(alg.isInitialized());
201+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", inputWS));
164202

165203
TS_ASSERT_THROWS(alg.executeAsChildAlg(), const std::runtime_error &);
166204
}
205+
206+
void test_Exec_Matrix_Workspace_with_Include_DetPos() {
207+
Workspace2D_sptr inputWS = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(3, 10, true);
208+
209+
CreateDetectorTable alg;
210+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
211+
TS_ASSERT(alg.isInitialized());
212+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(inputWS)));
213+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("IncludeDetectorPosition", true));
214+
TS_ASSERT_THROWS_NOTHING(alg.execute());
215+
TS_ASSERT(alg.isExecuted());
216+
217+
// Not setting an output workspace name should give the name:
218+
//[input workspace name] + "-Detectors"
219+
TableWorkspace_sptr ws;
220+
TS_ASSERT_THROWS_NOTHING(
221+
ws = AnalysisDataService::Instance().retrieveWS<TableWorkspace>(inputWS->getName() + "-Detectors"));
222+
TS_ASSERT(ws);
223+
224+
if (!ws) {
225+
return;
226+
}
227+
228+
// Check the results
229+
TS_ASSERT_EQUALS(ws->columnCount(), 12); // extra column compared to test_Exec_Matrix_Workspace
230+
TS_ASSERT_EQUALS(ws->rowCount(), 3);
231+
TS_ASSERT_EQUALS(ws->cell<int>(0, 1), 1); // Spectrum No should be 1, if not in the exception
232+
TS_ASSERT_EQUALS(ws->cell<V3D>(1, 11),
233+
V3D(0.0, 0.0, -9.0)); // Last two are monitors, first position should be (0.0, 0.0, -9.0)
234+
235+
// Remove workspace from the data service.
236+
AnalysisDataService::Instance().remove(ws->getName());
237+
}
238+
239+
void test_Exec_Matrix_Workspace_with_no_valid_spectra_include_DetPos() {
240+
Workspace2D_sptr inputWS = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(1, 10);
241+
auto &spec = inputWS->getSpectrum(0);
242+
spec.clearDetectorIDs(); // clear the detectors to test the exception catching
243+
244+
CreateDetectorTable alg;
245+
TS_ASSERT_THROWS_NOTHING(alg.initialize());
246+
TS_ASSERT(alg.isInitialized());
247+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(inputWS)));
248+
TS_ASSERT_THROWS_NOTHING(alg.setProperty("IncludeDetectorPosition", true));
249+
TS_ASSERT_THROWS_NOTHING(alg.execute());
250+
TS_ASSERT(alg.isExecuted());
251+
252+
// Not setting an output workspace name should give the name:
253+
//[input workspace name] + "-Detectors"
254+
TableWorkspace_sptr ws;
255+
TS_ASSERT_THROWS_NOTHING(
256+
ws = AnalysisDataService::Instance().retrieveWS<TableWorkspace>(inputWS->getName() + "-Detectors"));
257+
TS_ASSERT(ws);
258+
259+
if (!ws) {
260+
return;
261+
}
262+
263+
// Check the results
264+
TS_ASSERT_EQUALS(ws->columnCount(), 12);
265+
TS_ASSERT_EQUALS(ws->rowCount(), 1);
266+
TS_ASSERT_EQUALS(ws->cell<int>(0, 1), -1); // Spectrum No should be -1
267+
TS_ASSERT_EQUALS(ws->cell<V3D>(0, 11), V3D(0.0, 0.0, 0.0)); // Detector Position should be (0.0, 0.0, 0.0)
268+
269+
// Remove workspace from the data service.
270+
AnalysisDataService::Instance().remove(ws->getName());
271+
}
167272
};
168273

169274
class CreateDetectorTablePerformance : public CxxTest::TestSuite {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- :ref:`CreateDetectorTable<algm-CreateDetectorTable>` now has an optional argument, ``IncludeDetectorPosition``, which, if `True`, will add a column, ``Position``, to the end of the ``DetectorTable``. This column has the detector position as a ``V3D`` type object for each spectrum in the table.

0 commit comments

Comments
 (0)