-
Notifications
You must be signed in to change notification settings - Fork 122
/
CopyInstrumentParameters.cpp
147 lines (124 loc) · 5.74 KB
/
CopyInstrumentParameters.cpp
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
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidAlgorithms/CopyInstrumentParameters.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidGeometry/Instrument/DetectorInfo.h"
#include "MantidGeometry/Instrument/ParameterMap.h"
#include <algorithm>
namespace Mantid::Algorithms {
using std::size_t;
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(CopyInstrumentParameters)
using namespace Kernel;
using namespace API;
using namespace Geometry;
/// using namespace DataObjects;
void CopyInstrumentParameters::init() {
declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
"Name of the workspace giving the instrument");
declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::InOut),
"Name of the workspace receiving the instrument");
}
/** Executes the algorithm
* @throw std::out_of_range If a property is set to an invalid value for the
* input workspace
*/
void CopyInstrumentParameters::exec() {
// Get the giving workspace
m_givingWorkspace = getProperty("InputWorkspace");
// Get the receiving workspace
m_receivingWorkspace = getProperty("OutputWorkspace");
// Retrieve and validate the input properties
this->checkProperties();
if (m_different_instrument_sp) {
Instrument_const_sptr inst1 = m_givingWorkspace->getInstrument();
Instrument_const_sptr inst2 = m_receivingWorkspace->getInstrument();
auto Name1 = inst1->getName();
auto Name2 = inst2->getName();
Geometry::ParameterMap targMap;
// Get legacy ParameterMap, i.e., including masking, positions, rotations
// stored in map (instead of DetectorInfo).
const auto &givParams = inst1->makeLegacyParameterMap();
for (const auto &item : *givParams) {
IComponent *oldComponent = item.first;
const Geometry::IComponent *targComp = nullptr;
auto *pOldDet = dynamic_cast<IDetector *>(oldComponent);
if (pOldDet) {
detid_t detID = pOldDet->getID();
targComp = inst2->getBaseDetector(detID);
if (!targComp) {
g_log.warning() << "Target instrument does not have detector with ID " << detID << '\n';
continue;
}
} else {
std::string source_name = oldComponent->getFullName();
size_t nameStart = source_name.find(Name1);
std::string targ_name = source_name.replace(nameStart, nameStart + Name1.size(), Name2);
// existingComponents.
auto spTargComp = inst2->getComponentByName(targ_name);
if (!spTargComp) {
g_log.warning() << "Target instrument does not have component with full name: " << targ_name << '\n';
continue;
}
targComp = spTargComp->getBaseComponent();
}
// create shared pointer to independent copy of original parameter. Would
// be easy and nice to have cow_pointer instead of shared_ptr in the
// parameter map.
auto param = Parameter_sptr(item.second->clone());
// add new parameter to the maps for existing target component
targMap.add(targComp, param);
}
// Clear old parameters. We also want to clear fields stored in DetectorInfo
// (masking, positions, rotations). By setting the base instrument (which
// does not include a ParameterMap or DetectorInfo) we make use of the
// mechanism in ExperimentInfo that builds a clean DetectorInfo from the
// instrument being set.
m_receivingWorkspace->setInstrument(inst2->baseInstrument());
// ExperimentInfo::readParameterMap deals with extracting legacy information
// from ParameterMap.
m_receivingWorkspace->readParameterMap(targMap.asString());
} else {
// Same base instrument, copying the instrument is equivalent to copying the
// parameters in the ParameterMap and the DetectorInfo.
m_receivingWorkspace->setInstrument(m_givingWorkspace->getInstrument());
}
}
/** Retrieves the properties and checks that they have valid values.
* @throw std::invalid_argument If either workspace has no instrument or the
* instruments have different base instruments.
*/
void CopyInstrumentParameters::checkProperties() {
// Check that both workspaces have an instrument
Instrument_const_sptr inst = m_givingWorkspace->getInstrument();
if (!inst) {
throw std::invalid_argument("Input workspace has no instrument");
}
Instrument_const_sptr inst2 = m_receivingWorkspace->getInstrument();
if (!inst2) {
throw std::invalid_argument("Output workspace has no instrument");
}
Instrument_const_sptr baseInstGiv = inst->baseInstrument();
Instrument_const_sptr baseInstRec = inst2->baseInstrument();
// Check that both workspaces have the same instrument name
if (baseInstRec != baseInstGiv) {
m_different_instrument_sp = true;
g_log.warning() << "The base instrument in the output workspace is not the "
"same as the base instrument in the input workspace.\n";
}
}
Parallel::ExecutionMode CopyInstrumentParameters::getParallelExecutionMode(
const std::map<std::string, Parallel::StorageMode> &storageModes) const {
const auto in = storageModes.at("InputWorkspace");
const auto out = storageModes.at("InputWorkspace");
// Source instrument avaible only on master rank, so copying not possible if
// target requires it on non-master ranks.
if (in == Parallel::StorageMode::MasterOnly && in != out)
return Parallel::ExecutionMode::Invalid;
return Parallel::getCorrespondingExecutionMode(out);
}
} // namespace Mantid::Algorithms