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 // Create a copy (without the data) of the workspace - it will contain the
84 Workspace2D_sptr localWorkspace =
85 std::dynamic_pointer_cast<Workspace2D>(WorkspaceFactory::Instance().create(ws, ws->getNumberHistograms(), 2, 1));
86 if (!localWorkspace)
87 throw std::runtime_error("Failed when creating a Workspace2D from the input!");
88
89 const std::string groupfile = getProperty("GroupingFilename");
90
91 if (!groupfile.empty()) {
92 std::string filename(groupfile);
93 std::transform(filename.begin(), filename.end(), filename.begin(), tolower);
94 if (filename.find(".xml") != std::string::npos) {
95 readXMLGroupingFile(groupfile);
96 } else {
97 readGroupingFile(groupfile);
98 }
99 }
100
101 // Get the instrument.
102 const int64_t nHist = localWorkspace->getNumberHistograms();
103
104 // Determine whether the user wants to see unselected detectors or not
105 const std::string su = getProperty("ShowUnselected");
106 auto showunselected = bool(su == "True");
107 bool success = false;
108
109 for (int64_t i = 0; i < nHist; i++) {
110 auto &spec = localWorkspace->getSpectrum(i);
111 const auto &dets = spec.getDetectorIDs();
112 if (dets.empty()) // Nothing
113 {
114 spec.mutableY()[0] = 0.0;
115 continue;
116 }
117 // Find the first detector ID in the list
118 calmap::const_iterator it = calibration.find(*dets.begin());
119 if (it == calibration.end()) // Could not find the detector
120 {
121 spec.mutableY()[0] = 0.0;
122 continue;
123 }
124 if (showunselected) {
125 if (((*it).second).second == 0)
126 spec.mutableY()[0] = 0.0;
127 else
128 spec.mutableY()[0] = static_cast<double>(((*it).second).first);
129 } else
130 spec.mutableY()[0] = static_cast<double>(((*it).second).first);
131 success = true; // At least one detector is found in the cal file
132 }
133 progress(1);
134
135 calibration.clear();
136 if (!success) // Do some cleanup
137 {
138 localWorkspace.reset();
139 throw std::runtime_error("Fail to found a detector in " + groupfile + " existing in instrument " +
140 ws->getInstrumentName());
141 }
142 setProperty("OutputWorkspace", localWorkspace);
143}
144
145//-----------------------------------------------------------------------------------------------
150void ReadGroupsFromFile::readGroupingFile(const std::string &filename) {
151 std::ifstream grFile(filename.c_str());
152 if (!grFile.is_open()) {
153 g_log.error() << "Unable to open grouping file " << filename << '\n';
154 throw Exception::FileError("Error reading .cal file", filename);
155 }
156 calibration.clear();
157 std::string str;
158 while (getline(grFile, str)) {
159 // Comment, not read
160 if (str.empty() || str[0] == '#')
161 continue;
162 std::istringstream istr(str);
163 int n, udet, sel, group;
164 double offset;
165 istr >> n >> udet >> offset >> sel >> group;
166 calibration[udet] = std::make_pair(group, sel);
167 }
168 grFile.close();
169 progress(0.7);
170}
171
172//-----------------------------------------------------------------------------------------------
179void ReadGroupsFromFile::readXMLGroupingFile(const std::string &filename) {
180 Poco::XML::DOMParser xmlParser;
181 Poco::AutoPtr<Poco::XML::Document> file;
182 try {
183 file = xmlParser.parse(filename);
184 } catch (...) {
185 throw Kernel::Exception::FileError("Unable to parse file: ", filename);
186 }
187
188 Poco::XML::Element *root = file->documentElement();
189
190 if (!root->hasChildNodes()) {
191 throw Kernel::Exception::FileError("No root element in XML grouping file: ", filename);
192 }
193
194 Poco::AutoPtr<Poco::XML::NodeList> groups = root->getElementsByTagName("group");
195
196 if (groups->length() == 0) {
197 throw Kernel::Exception::FileError("XML group file contains no group elements:", filename);
198 }
199
200 auto nGroups = static_cast<unsigned int>(groups->length());
201 for (unsigned int i = 0; i < nGroups; i++) {
202 // Get the "detids" element from the grouping file
203 auto *elem = static_cast<Poco::XML::Element *>(groups->item(i));
204 Poco::XML::Element *group = elem->getChildElement("detids");
205
206 if (!group) {
207 throw Mantid::Kernel::Exception::FileError("XML Group File, group contains no <detids> element:", filename);
208 }
209
210 std::string ids = group->getAttribute("val");
211
213
214 if (data.begin() != data.end()) {
215 for (const auto &value : data) {
216 // cast the string to an int
217 int detID;
218 try {
219 detID = boost::lexical_cast<int>(value);
220 } catch (boost::bad_lexical_cast &) {
221 throw Mantid::Kernel::Exception::FileError("Could cast string to integer in input XML file", filename);
222 }
223
224 calibration.try_emplace(detID, std::pair<int, int>(i + 1, 1));
225 }
226 }
227 }
228
229 progress(0.7);
230}
231
232} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
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:426
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.
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55