Mantid
Loading...
Searching...
No Matches
ReadGroupsFromFile.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
17
18// Poco XML Headers for Grouping File
19#include <Poco/DOM/DOMParser.h>
20#include <Poco/DOM/Document.h>
21#include <Poco/DOM/Element.h>
22#include <Poco/DOM/NodeList.h>
23
24#include <fstream>
25
26using namespace Mantid::API;
27using namespace Mantid::Kernel;
28using namespace Mantid::Geometry;
29using namespace Mantid::DataObjects;
30
31namespace Mantid::Algorithms {
32
33// Register the class into the algorithm factory
34DECLARE_ALGORITHM(ReadGroupsFromFile)
35
36using namespace Kernel;
41
43
44//-----------------------------------------------------------------------------------------------
49
50 // The name of the instrument
51 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InstrumentWorkspace", "", Direction::Input,
52 std::make_shared<InstrumentValidator>()),
53 "A workspace that refers to the instrument of interest. You "
54 "can use [[LoadEmptyInstrument]] to create such a "
55 "workspace.");
56
57 // The calibration file that contains the grouping information
58 const std::vector<std::string> exts{".cal", ".xml"};
59 declareProperty(std::make_unique<FileProperty>("GroupingFileName", "", FileProperty::Load, exts),
60 "Either as a XML grouping file (see [[GroupDetectors]]) or as a "
61 "[[CalFile]] (.cal extension).");
62 // Flag to consider unselected detectors in the cal file
63 std::vector<std::string> select{"True", "False"};
64 declareProperty("ShowUnselected", "True", std::make_shared<StringListValidator>(select),
65 "Whether to show detectors that are not in any group");
66 // The output workspace (2D) that will contain the group information
68 std::make_unique<API::WorkspaceProperty<DataObjects::Workspace2D>>("OutputWorkspace", "", Direction::Output),
69 "The name of the output workspace");
70}
71
72//-----------------------------------------------------------------------------------------------
81 MatrixWorkspace_const_sptr ws = getProperty("InstrumentWorkspace");
82
83 // Get the instrument.
84 Instrument_const_sptr inst = ws->getInstrument();
85
86 // Create a copy (without the data) of the workspace - it will contain the
87 Workspace2D_sptr localWorkspace =
88 std::dynamic_pointer_cast<Workspace2D>(WorkspaceFactory::Instance().create(ws, ws->getNumberHistograms(), 2, 1));
89 if (!localWorkspace)
90 throw std::runtime_error("Failed when creating a Workspace2D from the input!");
91
92 const std::string groupfile = getProperty("GroupingFilename");
93
94 if (!groupfile.empty()) {
95 std::string filename(groupfile);
96 std::transform(filename.begin(), filename.end(), filename.begin(), tolower);
97 if (filename.find(".xml") != std::string::npos) {
98 readXMLGroupingFile(groupfile);
99 } else {
100 readGroupingFile(groupfile);
101 }
102 }
103
104 // Get the instrument.
105 const int64_t nHist = localWorkspace->getNumberHistograms();
106
107 // Determine whether the user wants to see unselected detectors or not
108 const std::string su = getProperty("ShowUnselected");
109 auto showunselected = bool(su == "True");
110 bool success = false;
111
112 for (int64_t i = 0; i < nHist; i++) {
113 auto &spec = localWorkspace->getSpectrum(i);
114 const auto &dets = spec.getDetectorIDs();
115 if (dets.empty()) // Nothing
116 {
117 spec.mutableY()[0] = 0.0;
118 continue;
119 }
120 // Find the first detector ID in the list
121 calmap::const_iterator it = calibration.find(*dets.begin());
122 if (it == calibration.end()) // Could not find the detector
123 {
124 spec.mutableY()[0] = 0.0;
125 continue;
126 }
127 if (showunselected) {
128 if (((*it).second).second == 0)
129 spec.mutableY()[0] = 0.0;
130 else
131 spec.mutableY()[0] = static_cast<double>(((*it).second).first);
132 } else
133 spec.mutableY()[0] = static_cast<double>(((*it).second).first);
134 success = true; // At least one detector is found in the cal file
135 }
136 progress(1);
137
138 calibration.clear();
139 if (!success) // Do some cleanup
140 {
141 localWorkspace.reset();
142 throw std::runtime_error("Fail to found a detector in " + groupfile + " existing in instrument " + inst->getName());
143 }
144 setProperty("OutputWorkspace", localWorkspace);
145}
146
147//-----------------------------------------------------------------------------------------------
152void ReadGroupsFromFile::readGroupingFile(const std::string &filename) {
153 std::ifstream grFile(filename.c_str());
154 if (!grFile.is_open()) {
155 g_log.error() << "Unable to open grouping file " << filename << '\n';
156 throw Exception::FileError("Error reading .cal file", filename);
157 }
158 calibration.clear();
159 std::string str;
160 while (getline(grFile, str)) {
161 // Comment, not read
162 if (str.empty() || str[0] == '#')
163 continue;
164 std::istringstream istr(str);
165 int n, udet, sel, group;
166 double offset;
167 istr >> n >> udet >> offset >> sel >> group;
168 calibration[udet] = std::make_pair(group, sel);
169 }
170 grFile.close();
171 progress(0.7);
172}
173
174//-----------------------------------------------------------------------------------------------
181void ReadGroupsFromFile::readXMLGroupingFile(const std::string &filename) {
182 Poco::XML::DOMParser xmlParser;
183 Poco::AutoPtr<Poco::XML::Document> file;
184 try {
185 file = xmlParser.parse(filename);
186 } catch (...) {
187 throw Kernel::Exception::FileError("Unable to parse file: ", filename);
188 }
189
190 Poco::XML::Element *root = file->documentElement();
191
192 if (!root->hasChildNodes()) {
193 throw Kernel::Exception::FileError("No root element in XML grouping file: ", filename);
194 }
195
196 Poco::AutoPtr<Poco::XML::NodeList> groups = root->getElementsByTagName("group");
197
198 if (groups->length() == 0) {
199 throw Kernel::Exception::FileError("XML group file contains no group elements:", filename);
200 }
201
202 auto nGroups = static_cast<unsigned int>(groups->length());
203 for (unsigned int i = 0; i < nGroups; i++) {
204 // Get the "detids" element from the grouping file
205 auto *elem = static_cast<Poco::XML::Element *>(groups->item(i));
206 Poco::XML::Element *group = elem->getChildElement("detids");
207
208 if (!group) {
209 throw Mantid::Kernel::Exception::FileError("XML Group File, group contains no <detids> element:", filename);
210 }
211
212 std::string ids = group->getAttribute("val");
213
215
216 if (data.begin() != data.end()) {
217 for (const auto &value : data) {
218 // cast the string to an int
219 int detID;
220 try {
221 detID = boost::lexical_cast<int>(value);
222 } catch (boost::bad_lexical_cast &) {
223 throw Mantid::Kernel::Exception::FileError("Could cast string to integer in input XML file", filename);
224 }
225
226 calibration.try_emplace(detID, std::pair<int, int>(i + 1, 1));
227 }
228 }
229 }
230
231 progress(0.7);
232}
233
234} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
double value
The value of the point.
Definition FitMW.cpp:51
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
A specialized class for dealing with file properties.
@ Load
allowed here which will be passed to the algorithm
Base MatrixWorkspace Abstract Class.
A property class for workspaces.
void exec() override
Execution code.
void init() override
Initialisation code.
void readXMLGroupingFile(const std::string &filename)
Read an XML Grouping File.
void readGroupingFile(const std::string &filename)
Read a grouping file and construct the calibration map.
calmap calibration
Calibration map containing the detector entries found in the *.cal file.
Records the filename and the description of failure.
Definition Exception.h:98
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Iterator begin()
Iterator referring to first element in the container.
@ TOK_TRIM
remove leading and trailing whitespace from tokens
Iterator end()
Iterator referring to the past-the-end element in the container.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54