Mantid
Loading...
Searching...
No Matches
LoadCSNSNexus.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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 +
7
8//----------------------------------------------------------------------
9// Includes
10//----------------------------------------------------------------------
11
19
20#include <algorithm>
21/************************/
22
23namespace Mantid::DataHandling {
24
25using namespace Kernel;
26using namespace API;
27using namespace DataObjects;
28
29Kernel::Logger g_log("LoadCSNSNexus");
30
33
35const std::string LoadCSNSNexus::name() const { return "LoadCSNSNexus"; }
36
38int LoadCSNSNexus::version() const { return 1; }
39
41const std::string LoadCSNSNexus::category() const { return "DataHandling\\Nexus"; }
42
43//----------------------------------------------------------------------------------------------
47 declareProperty(std::make_unique<PropertyWithValue<std::string>>("Instrument", "GPPD", Direction::Input),
48 "Different instrument with different detector combinations");
49
50 const std::vector<std::string> exts{".h5", ".nxs"};
51 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
52 "The name of the Nexus file to load");
53
54 declareProperty(std::make_unique<PropertyWithValue<std::string>>("NXentryName", "csns", Direction::Input),
55 "Optional: Name of entry (default csns)");
56
57 declareProperty(std::make_unique<PropertyWithValue<bool>>("LoadBank", true, Direction::Input),
58 "Default true: load bank data, false: load monitor data.");
59
60 declareProperty(std::make_unique<ArrayProperty<std::string>>("Bankname", Direction::Input),
61 "Optional: A comma-separated list of bank/monitor to read");
62
63 declareProperty(std::make_unique<ArrayProperty<uint32_t>>("StartT0", Direction::Input),
64 "Optional: A comma-separated list of StartNo of T0 to read.");
66 "Optional: A comma-separated list of endNo of T0 to read.");
67
68 declareProperty(std::make_unique<PropertyWithValue<bool>>("LoadEvent", false, Direction::Input),
69 "Default false: load event data, true: load histogram data.");
70
71 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
72 "An output orkspace.");
73
74 const std::string grp1 = "Bank/Monitor";
75 setPropertyGroup("Bankname", grp1);
76 setPropertyGroup("loadBank", grp1);
77
78 const std::string grp2 = "FilterByPulse";
79 setPropertyGroup("LoadEvent", grp2);
80 setPropertyGroup("StartT0", grp2);
81 setPropertyGroup("EndT0", grp2);
82}
83
89Types::Core::DateAndTime LoadCSNSNexus::getExperimentTime(const std::string &typeName) {
90 Types::Core::DateAndTime data;
91 std::string expTime;
92 m_file->openGroup(m_entry, "NXentry");
93 std::map<std::string, std::string> entries = m_file->getEntries();
94 if (entries.find(typeName) != entries.end())
95
96 m_file->readData(typeName, expTime);
97 else
98 throw std::runtime_error("No experiment time in the NXS file!");
99 m_file->closeGroup();
100 try {
101 data = Mantid::Types::Core::DateAndTime(expTime);
102 } catch (...) {
103 data = Mantid::Types::Core::DateAndTime("2100-12-31T00:00:00+08:00");
104 }
105 return data;
106}
107
113std::vector<std::string> LoadCSNSNexus::getGPPDModules(const std::string &bankName) {
114 int firstModuleId(-1), secondModuleId(-1);
115 if (bankName == "bank3") {
116 firstModuleId = 1;
117 secondModuleId = 2;
118 } else if (bankName == "bank2") {
119 firstModuleId = 3;
120 secondModuleId = 4;
121 } else if (bankName == "bank1") {
122 firstModuleId = 5;
123 secondModuleId = 6;
124 }
125
126 std::vector<std::string> data;
127 m_file->openGroup(m_entry, "NXentry");
128 m_file->openGroup("instrument", "NXinstrument");
129 auto entries = m_file->getEntries();
130 for (const auto &it : entries) {
131 const auto &name = it.first;
132 if (name.compare(0, 7, "module" + std::to_string(firstModuleId)) == 0 ||
133 name.compare(0, 7, "module" + std::to_string(secondModuleId)) == 0) {
134 data.emplace_back(name);
135 }
136 }
137 m_file->closeGroup();
138 m_file->closeGroup();
139 return data;
140}
141
147bool LoadCSNSNexus::checkBanknames(const std::vector<std::string> &inputNames) {
148 if (inputNames.size() == 0)
149 return false;
150 else if (inputNames.size() > 1) {
151 return std::all_of(inputNames.cbegin(), inputNames.cend(),
152 [](const auto &name) { return name.compare(0, 6, "module") == 0; });
153 } else
154 return true;
155}
162std::vector<std::string> LoadCSNSNexus::getModules(const std::string &inst,
163 const std::vector<std::string> &inputNames) {
164 std::vector<std::string> data;
165 if (inst == "SANS" || inst == "MR")
166 data.push_back("module1");
167 else if (inst == "GPPD") {
168 for (const auto &name : inputNames) {
169 if (name.compare(0, 4, "bank") == 0)
170 data = getGPPDModules(name);
171 else
172 data.push_back(name);
173 }
174 }
175 return data;
176}
177
183std::vector<int64_t> LoadCSNSNexus::getPixelId(const std::vector<std::string> &inputList) {
184 std::vector<int64_t> _tmp;
185 std::vector<int64_t> pixelId;
186 m_file->openGroup(m_entry, "NXentry");
187 m_file->openGroup("instrument", "NXinstrument");
188 auto entries = m_file->getEntries();
189 for (const auto &name : inputList) {
190 auto it = entries.find(name);
191 if (it != entries.end()) {
192 m_file->openGroup(it->first, it->second);
193 m_file->readData("pixel_id", _tmp);
194 pixelId.insert(pixelId.end(), _tmp.begin(), _tmp.end());
195 m_file->closeGroup();
196 }
197 }
198 sort(pixelId.begin(), pixelId.end());
199 m_file->closeGroup();
200 m_file->closeGroup();
201 return pixelId;
202}
203
209std::vector<uint32_t> LoadCSNSNexus::getTimeBin(const std::string &typeName) {
210 std::vector<int> tmp;
211 m_file->openGroup(m_entry, "NXentry");
212 m_file->openGroup("instrument", "NXinstrument");
213 auto entries = m_file->getEntries();
214 for (const auto &[name, nodeType] : entries) {
215 if ((name.compare(0, 6, typeName) == 0) || (name.compare(0, 7, typeName) == 0)) {
216 m_file->openGroup(name, nodeType);
217 m_file->readData("time_of_flight", tmp);
218 m_file->closeGroup();
219 break;
220 }
221 }
222 m_file->closeGroup();
223 m_file->closeGroup();
224 std::vector<uint32_t> timeBin(tmp.begin(), tmp.end());
225 return timeBin;
226}
227
233std::vector<uint32_t> LoadCSNSNexus::getHistData(const std::vector<std::string> &inputList) {
234 std::vector<int> tmp;
235 std::vector<uint32_t> data;
236
237 m_file->openGroup("csns", "NXentry");
238 m_file->openGroup("histogram_data", "NXcollection");
239 auto entries = m_file->getEntries();
240 for (const auto &name : inputList) {
241 auto it = entries.find(name);
242 if (it != entries.end()) {
243 m_file->openGroup(it->first, it->second);
244 m_file->readData("histogram_data", tmp);
245 data.insert(data.end(), tmp.begin(), tmp.end());
246 m_file->closeGroup();
247 }
248 }
249 m_file->closeGroup();
250 m_file->closeGroup();
251 return data;
252}
253
261void LoadCSNSNexus::loadHistData(MatrixWorkspace_sptr &workspace, const std::vector<uint32_t> &timeOfFlight,
262 size_t pidNums, const std::vector<uint32_t> &histData) {
263 size_t timeNums = timeOfFlight.size();
264 MantidVecPtr x, e;
265 MantidVec xA;
266 MantidVec xRef(timeNums);
267
268 std::copy(timeOfFlight.cbegin(), timeOfFlight.cend(), xRef.begin());
269
270 std::vector<double> err;
271 err.resize(histData.size());
272 std::transform(histData.cbegin(), histData.cend(), std::back_inserter(err),
273 [](auto const &hist) { return sqrt(hist); });
274
275 auto it_start = histData.begin();
276 auto it_end = it_start + timeNums - 1;
277
278 auto it_err_start = err.begin();
279 auto it_err_end = it_err_start + timeNums - 1;
280
281 size_t hist = 0;
282 while (hist < pidNums) {
283 auto &Y = workspace->mutableY(hist);
284 auto &E = workspace->mutableE(hist);
285 Y.assign(it_start, it_end);
286 E.assign(it_err_start, it_err_end);
287 it_start += (timeNums - 1);
288 it_end += (timeNums - 1);
289 it_err_start += (timeNums - 1);
290 it_err_end += (timeNums - 1);
291 auto toPass = Kernel::make_cow<HistogramData::HistogramX>(xRef);
292 workspace->setX(hist, toPass);
293 ++hist;
294 }
295}
296
305std::multimap<uint32_t, std::pair<float, int64_t>>
306LoadCSNSNexus::getEventData(const std::vector<std::string> &inputList, const std::vector<uint32_t> &startList,
307 const std::vector<uint32_t> &endList, const std::vector<int64_t> &pids) {
308 std::vector<int64_t> pid_tmp;
309 std::vector<int64_t> pidList;
310 std::vector<int64_t> t0_tmp;
311 std::vector<int64_t> t0List;
312 std::vector<float> tof_tmp;
313 std::vector<float> tofList;
314 std::pair<float, int64_t> tofPulse;
315 m_file->openGroup(m_entry, "NXentry");
316 m_file->openGroup("event_data", "NXcollection");
317 auto entries = m_file->getEntries();
318 for (auto const &name : inputList) {
319 auto it = entries.find(name);
320 if (it != entries.end()) {
321 m_file->openGroup(it->first, it->second);
322 m_file->readData("event_pulse_time", t0_tmp);
323 m_file->readData("event_pixel_id", pid_tmp);
324 m_file->readData("event_time_of_flight", tof_tmp);
325 if (startList.size() == 0) {
326 t0List.insert(t0List.end(), t0_tmp.begin(), t0_tmp.end());
327 pidList.insert(pidList.end(), pid_tmp.begin(), pid_tmp.end());
328 tofList.insert(tofList.end(), tof_tmp.begin(), tof_tmp.end());
329 } else {
330 for (size_t k = 0; k < t0_tmp.size(); k++) {
331 for (size_t j = 0; j < startList.size(); j++) {
332 if (t0_tmp[k] >= startList[j] && t0_tmp[k] <= endList[j]) {
333 t0List.push_back(t0_tmp[k]);
334 pidList.push_back(pid_tmp[k]);
335 tofList.push_back(tof_tmp[k]);
336 }
337 }
338 }
339 }
340 m_file->closeGroup();
341 }
342 }
343 tof_tmp.clear();
344 t0_tmp.clear();
345 pid_tmp.clear();
346 m_file->closeGroup();
347 m_file->closeGroup();
348 std::map<int64_t, uint32_t> mapping;
349 uint32_t p = 0;
350 for (const auto &pidNum : pids) {
351 mapping.insert(std::map<int64_t, uint32_t>::value_type(pidNum, p));
352 p++;
353 }
354 std::multimap<uint32_t, std::pair<float, int64_t>> data;
355 for (size_t i = 0; i < pidList.size(); i++) {
356 uint32_t specNo = mapping[pidList[i]];
357 tofPulse = std::make_pair(tofList[i], t0List[i]);
358 data.insert(std::multimap<uint32_t, std::pair<float, int64_t>>::value_type(specNo, tofPulse));
359 }
360
361 tofList.clear();
362 t0List.clear();
363 pidList.clear();
364 return data;
365}
366
374void LoadCSNSNexus::loadEventData(EventWorkspace_sptr &workspace, const std::vector<uint32_t> &timeOfFlight,
375 size_t pidNums, const std::multimap<uint32_t, std::pair<float, int64_t>> &evtData) {
376 workspace->initialize(pidNums, 1, 1);
377 float m_tof;
378 uint64_t m_pulseTime;
379 int endNum = static_cast<int>(pidNums);
380 for (auto i = 0; i != endNum; i++) {
381 auto it = evtData.find(i);
382 if (it != evtData.end()) {
383 for (size_t j = 0; j != evtData.count(i); j++, it++) {
384 m_pulseTime = it->second.second;
385 m_tof = it->second.first;
386 workspace->getSpectrum(i) += Types::Event::TofEvent(m_tof, m_pulseTime);
387 }
388 workspace->getSpectrum(i).setSpectrumNo(i);
389 }
390 }
391 double dataMin = *(timeOfFlight.begin());
392 double dataMax = *(timeOfFlight.end() - 1);
393 workspace->setAllX(HistogramData::BinEdges{dataMin, dataMax});
394}
395
399 g_log.information() << "start load csns nexus data " << std::endl;
400 const std::string m_filename = getPropertyValue("Filename");
401 m_entry = getPropertyValue("NXentryName");
402 const std::vector<std::string> bankNames = getProperty("Bankname");
403 m_file = std::make_unique<::NeXus::File>(m_filename, NXACC_READ);
404 const bool m_loadBank = getProperty("LoadBank");
405 const bool m_loadEvent = getProperty("LoadEvent");
406 const auto start_time = getExperimentTime("start_time_utc");
407 const auto end_time = getExperimentTime("end_time_utc");
408 g_log.information() << "load experiment time " << std::endl;
409
410 MatrixWorkspace_sptr ws_hist;
412
413 if (m_loadBank) {
414 const std::string instName = getPropertyValue("Instrument");
415 const bool m_inputCheck = checkBanknames(bankNames);
416 if (m_inputCheck) {
417 m_modules = getModules(instName, bankNames);
418 std::vector<int64_t> pid_bank = getPixelId(m_modules);
419 std::vector<uint32_t> tof_bank = getTimeBin("module");
420
421 if (m_loadEvent) {
422 g_log.information() << "load event data " << std::endl;
423 std::vector<uint32_t> startT0 = getProperty("startT0");
424 std::vector<uint32_t> endT0 = getProperty("endT0");
425 std::multimap<uint32_t, std::pair<float, int64_t>> evtData = getEventData(m_modules, startT0, endT0, pid_bank);
426 loadEventData(ws_evt, tof_bank, pid_bank.size(), evtData);
427 ws_evt->mutableRun().setStartAndEndTime(start_time, end_time);
428 ws_evt->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
429 ws_evt->setYUnit("Counts");
430
431 } else {
432 g_log.information() << "load histogram data " << std::endl;
433 ws_hist =
434 WorkspaceFactory::Instance().create("Workspace2D", pid_bank.size(), tof_bank.size(), tof_bank.size() - 1);
435 std::vector<uint32_t> histData = getHistData(m_modules);
436 loadHistData(ws_hist, tof_bank, pid_bank.size(), histData);
437 ws_hist->mutableRun().setStartAndEndTime(start_time, end_time);
438 ws_hist->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
439 ws_hist->setYUnit("Counts");
440 }
441 } else {
442 throw std::runtime_error("Error in Banknames input!");
443 }
444 } else {
445
446 g_log.information() << "load monitor data " << std::endl;
447 std::vector<int64_t> pid_mon = getPixelId(bankNames);
448 std::vector<uint32_t> tof_mon = getTimeBin("monitor");
449 ws_hist = WorkspaceFactory::Instance().create("Workspace2D", pid_mon.size(), tof_mon.size(), tof_mon.size() - 1);
450 std::vector<uint32_t> histData_mon = getHistData(bankNames);
451 loadHistData(ws_hist, tof_mon, pid_mon.size(), histData_mon);
452 ws_hist->mutableRun().setStartAndEndTime(start_time, end_time);
453 ws_hist->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
454 ws_hist->setYUnit("Counts");
455 }
456
457 if (m_loadEvent) {
458 setProperty("OutputWorkspace", ws_evt);
459 } else {
460 setProperty("OutputWorkspace", ws_hist);
461 }
462}
463} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
gsl_vector * tmp
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
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
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
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
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
A property class for workspaces.
LoadCSNSNexus : TODO: DESCRIPTION.
Definition: LoadCSNSNexus.h:21
void loadHistData(API::MatrixWorkspace_sptr &workspace, const std::vector< uint32_t > &timeOfFlight, size_t pidNums, const std::vector< uint32_t > &histData)
load histogram data into workspace
std::vector< uint32_t > getTimeBin(const std::string &typeName)
Return time-of-flight.
std::vector< std::string > m_modules
Definition: LoadCSNSNexus.h:54
std::vector< uint32_t > getHistData(const std::vector< std::string > &inputList)
Get histogram data.
const std::string category() const override
Algorithm's category for identification.
void exec() override
Execute the algorithm.
void init() override
Initialize the algorithm's properties.
std::multimap< uint32_t, std::pair< float, int64_t > > getEventData(const std::vector< std::string > &inputList, const std::vector< uint32_t > &startList, const std::vector< uint32_t > &endList, const std::vector< int64_t > &pids)
Get event data.
std::unique_ptr<::NeXus::File > m_file
Definition: LoadCSNSNexus.h:52
int version() const override
Algorithm's version for identification.
Types::Core::DateAndTime getExperimentTime(const std::string &typeName)
Return the start or end time of experiment.
void loadEventData(DataObjects::EventWorkspace_sptr &workspace, const std::vector< uint32_t > &timeOfFlight, size_t pidNums, const std::multimap< uint32_t, std::pair< float, int64_t > > &evtData)
load event data into workspace
bool checkBanknames(const std::vector< std::string > &inputNames)
Judge the input of Bankname.
const std::string name() const override
Empty default constructor.
std::vector< int64_t > getPixelId(const std::vector< std::string > &inputList)
Return pixel id.
std::vector< std::string > getModules(const std::string &inst, const std::vector< std::string > &inputNames)
Return modules for special instrument.
std::vector< std::string > getGPPDModules(const std::string &bankName)
Return modules for special bankName at GPPD.
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Implements a copy on write data template.
Definition: cow_ptr.h:41
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54