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 if (!success)
135 success = true; // At least one detector is found in the cal file
136 }
137 progress(1);
138
139 calibration.clear();
140 if (!success) // Do some cleanup
141 {
142 localWorkspace.reset();
143 throw std::runtime_error("Fail to found a detector in " + groupfile + " existing in instrument " + inst->getName());
144 }
145 setProperty("OutputWorkspace", localWorkspace);
146}
147
148//-----------------------------------------------------------------------------------------------
153void ReadGroupsFromFile::readGroupingFile(const std::string &filename) {
154 std::ifstream grFile(filename.c_str());
155 if (!grFile.is_open()) {
156 g_log.error() << "Unable to open grouping file " << filename << '\n';
157 throw Exception::FileError("Error reading .cal file", filename);
158 }
159 calibration.clear();
160 std::string str;
161 while (getline(grFile, str)) {
162 // Comment, not read
163 if (str.empty() || str[0] == '#')
164 continue;
165 std::istringstream istr(str);
166 int n, udet, sel, group;
167 double offset;
168 istr >> n >> udet >> offset >> sel >> group;
169 calibration[udet] = std::make_pair(group, sel);
170 }
171 grFile.close();
172 progress(0.7);
173}
174
175//-----------------------------------------------------------------------------------------------
182void ReadGroupsFromFile::readXMLGroupingFile(const std::string &filename) {
183 Poco::XML::DOMParser xmlParser;
184 Poco::AutoPtr<Poco::XML::Document> file;
185 try {
186 file = xmlParser.parse(filename);
187 } catch (...) {
188 throw Kernel::Exception::FileError("Unable to parse file: ", filename);
189 }
190
191 Poco::XML::Element *root = file->documentElement();
192
193 if (!root->hasChildNodes()) {
194 throw Kernel::Exception::FileError("No root element in XML grouping file: ", filename);
195 }
196
197 Poco::AutoPtr<Poco::XML::NodeList> groups = root->getElementsByTagName("group");
198
199 if (groups->length() == 0) {
200 throw Kernel::Exception::FileError("XML group file contains no group elements:", filename);
201 }
202
203 auto nGroups = static_cast<unsigned int>(groups->length());
204 for (unsigned int i = 0; i < nGroups; i++) {
205 // Get the "detids" element from the grouping file
206 auto *elem = static_cast<Poco::XML::Element *>(groups->item(i));
207 Poco::XML::Element *group = elem->getChildElement("detids");
208
209 if (!group) {
210 throw Mantid::Kernel::Exception::FileError("XML Group File, group contains no <detids> element:", filename);
211 }
212
213 std::string ids = group->getAttribute("val");
214
216
217 if (data.begin() != data.end()) {
218 for (const auto &value : data) {
219 // cast the string to an int
220 int detID;
221 try {
222 detID = boost::lexical_cast<int>(value);
223 } catch (boost::bad_lexical_cast &) {
224 throw Mantid::Kernel::Exception::FileError("Could cast string to integer in input XML file", filename);
225 }
226
227 if (calibration.find(detID) == calibration.end()) {
228 // add detector to a group
229 calibration[detID] = std::pair<int, int>(i + 1, 1);
230 }
231 }
232 }
233 }
234
235 progress(0.7);
236}
237
238} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
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:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
A specialized class for dealing with file properties.
Definition: FileProperty.h:42
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
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:77
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