Mantid
Loading...
Searching...
No Matches
FilterEvents.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 +
10#include "MantidAPI/Run.h"
12#include "MantidAPI/TableRow.h"
23#include "MantidHistogramData/Histogram.h"
31#include "MantidKernel/System.h"
34
35#include <memory>
36#include <sstream>
37
38using namespace Mantid;
39using namespace Mantid::Kernel;
40using namespace Mantid::API;
41using namespace Mantid::DataObjects;
42using namespace Mantid::HistogramData;
43using namespace Mantid::Geometry;
44using Types::Core::DateAndTime;
45
46using namespace std;
47
48const int64_t TOLERANCE(1000000); // splitter time tolerance in nano-second.
49 // this value has resolution to 10000Hz
50
54
55namespace Mantid::Algorithms {
56
57DECLARE_ALGORITHM(FilterEvents)
58
59
62 : m_eventWS(), m_splittersWorkspace(), m_splitterTableWorkspace(), m_matrixSplitterWS(), m_detCorrectWorkspace(),
63 m_useSplittersWorkspace(false), m_useArbTableSplitters(false), m_targetWorkspaceIndexSet(), m_splitters(),
64 m_outputWorkspacesMap(), m_wsNames(), m_detTofOffsets(), m_detTofFactors(), m_filterByPulseTime(false),
65 m_informationWS(), m_hasInfoWS(), m_progress(0.), m_outputWSNameBase(), m_toGroupWS(false), m_vecSplitterTime(),
66 m_vecSplitterGroup(), m_splitSampleLogs(false), m_useDBSpectrum(false), m_dbWSIndex(-1),
67 m_tofCorrType(NoneCorrect), m_specSkipType(), m_vecSkip(), m_isSplittersRelativeTime(false), m_filterStartTime(0),
68 m_runStartTime(0) {}
69
73 declareProperty(std::make_unique<API::WorkspaceProperty<EventWorkspace>>("InputWorkspace", "", Direction::Input),
74 "An input event workspace");
75
76 declareProperty(std::make_unique<API::WorkspaceProperty<API::Workspace>>("SplitterWorkspace", "", Direction::Input),
77 "An input SpilltersWorskpace for filtering");
78
79 declareProperty("OutputWorkspaceBaseName", "OutputWorkspace",
80 "The base name to use for the output workspace. The output "
81 "workspace names are a combination of this and the index in "
82 "splitter.");
83
84 declareProperty(std::make_unique<WorkspaceProperty<TableWorkspace>>("InformationWorkspace", "", Direction::Input,
86 "Optional output for the information of each splitter "
87 "workspace index.");
88
89 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputTOFCorrectionWorkspace", "TOFCorrectWS",
91 "Name of output workspace for TOF correction factor. ");
92
93 declareProperty("FilterByPulseTime", false,
94 "Filter the event by its pulse time only for slow sample "
95 "environment log. This option can make execution of "
96 "algorithm faster. But it lowers precision.");
97
98 declareProperty("GroupWorkspaces", false,
99 "Option to group all the output "
100 "workspaces. Group name will be "
101 "OutputWorkspaceBaseName.");
102
103 declareProperty("OutputWorkspaceIndexedFrom1", false,
104 "If selected, the minimum output workspace is indexed from 1 "
105 "and continuous.");
106
107 // TOF correction
108 vector<string> corrtypes{"None", "Customized", "Direct", "Elastic", "Indirect"};
109 declareProperty("CorrectionToSample", "None", std::make_shared<StringListValidator>(corrtypes),
110 "Type of correction on neutron events to sample time from "
111 "detector time. ");
112
113 declareProperty(std::make_unique<WorkspaceProperty<TableWorkspace>>("DetectorTOFCorrectionWorkspace", "",
115 "Name of table workspace containing the log "
116 "time correction factor for each detector. ");
117 setPropertySettings("DetectorTOFCorrectionWorkspace",
118 std::make_unique<VisibleWhenProperty>("CorrectionToSample", IS_EQUAL_TO, "Customized"));
119
120 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
121 mustBePositive->setLower(0.0);
122 declareProperty("IncidentEnergy", EMPTY_DBL(), mustBePositive,
123 "Value of incident energy (Ei) in meV in direct mode.");
124 setPropertySettings("IncidentEnergy",
125 std::make_unique<VisibleWhenProperty>("CorrectionToSample", IS_EQUAL_TO, "Direct"));
126
127 // Algorithm to spectra without detectors
128 vector<string> spec_no_det{"Skip", "Skip only if TOF correction"};
129 declareProperty("SpectrumWithoutDetector", "Skip", std::make_shared<StringListValidator>(spec_no_det),
130 "Approach to deal with spectrum without detectors. ");
131
132 declareProperty("SplitSampleLogs", true,
133 "If selected, all sample logs will be splitted by the "
134 "event splitters. It is not recommended for fast event "
135 "log splitters. ");
136
137 declareProperty("NumberOutputWS", 0, "Number of output output workspace splitted. ", Direction::Output);
138
139 declareProperty("DBSpectrum", EMPTY_INT(), "Spectrum (workspace index) for debug purpose. ");
140
141 declareProperty(std::make_unique<ArrayProperty<string>>("OutputWorkspaceNames", Direction::Output),
142 "List of output workspaces names");
143
144 declareProperty("RelativeTime", false,
145 "Flag to indicate that in the input Matrix splitting workspace,"
146 "the time indicated by X-vector is relative to either run start time or "
147 "some indicted time.");
148
149 declareProperty("FilterStartTime", "", "Start time for splitters that can be parsed to DateAndTime.");
150
151 declareProperty(std::make_unique<ArrayProperty<std::string>>("TimeSeriesPropertyLogs"),
152 "List of name of sample logs of TimeSeriesProperty format. "
153 "They will be either excluded from splitting if ExcludedSpecifiedLogs is "
154 "specified as True. Or "
155 "They will be the only TimeSeriesProperty sample logs that will be split "
156 "to child workspaces.");
157
158 declareProperty("ExcludeSpecifiedLogs", true,
159 "If true, all the TimeSeriesProperty logs listed will be "
160 "excluded from duplicating. "
161 "Otherwise, only those specified logs will be split.");
162
163 declareProperty("DescriptiveOutputNames", false,
164 "If selected, the names of the output workspaces will "
165 "include information about each slice.");
166}
167
168std::map<std::string, std::string> FilterEvents::validateInputs() {
169 const std::string SPLITER_PROP_NAME = "SplitterWorkspace";
170 std::map<std::string, std::string> result;
171
172 // check the splitters workspace for special behavior
173 API::Workspace_const_sptr splitter = this->getProperty(SPLITER_PROP_NAME);
174 // SplittersWorkspace is a special type that needs no further checking
175 if (bool(std::dynamic_pointer_cast<const SplittersWorkspace>(splitter))) {
176 if (std::dynamic_pointer_cast<const SplittersWorkspace>(splitter)->rowCount() == 0)
177 result[SPLITER_PROP_NAME] = "SplittersWorkspace must have rows defined";
178 } else {
179 const auto table = std::dynamic_pointer_cast<const TableWorkspace>(splitter);
180 const auto matrix = std::dynamic_pointer_cast<const MatrixWorkspace>(splitter);
181 if (bool(table)) {
182 if (table->columnCount() != 3)
183 result[SPLITER_PROP_NAME] = "TableWorkspace must have 3 columns";
184 else if (table->rowCount() == 0)
185 result[SPLITER_PROP_NAME] = "TableWorkspace must have rows defined";
186 } else if (bool(matrix)) {
187 if (matrix->getNumberHistograms() == 1) {
188 if (!matrix->isHistogramData())
189 result[SPLITER_PROP_NAME] = "MatrixWorkspace must be histogram";
190 } else {
191 result[SPLITER_PROP_NAME] = "MatrixWorkspace can have only one histogram";
192 }
193 } else {
194 result[SPLITER_PROP_NAME] = "Incompatible workspace type";
195 }
196 }
197
198 const string correctiontype = getPropertyValue("CorrectionToSample");
199 if (correctiontype == "Direct") {
200 double ei = getProperty("IncidentEnergy");
201 if (isEmpty(ei)) {
202 EventWorkspace_const_sptr inputWS = this->getProperty("InputWorkspace");
203 if (!inputWS->run().hasProperty("Ei")) {
204 const string msg("InputWorkspace does not have Ei. Must specify IncidentEnergy");
205 result["CorrectionToSample"] = msg;
206 result["IncidentEnergy"] = msg;
207 }
208 }
209 } else if (correctiontype == "Customized") {
210 TableWorkspace_const_sptr correctionWS = getProperty("DetectorTOFCorrectionWorkspace");
211 if (!correctionWS) {
212 const string msg("Must specify correction workspace with CorrectionToSample=Custom");
213 result["CorrectionToSample"] = msg;
214 result["DetectorTOFCorrectionWorkspace"] = msg;
215 }
216 }
217 // "None" and "Elastic" and "Indirect" don't require extra information
218
219 return result;
220}
221
225 // Process algorithm properties
227
228 // Examine workspace for detectors
230
231 // Parse splitters
232 m_progress = 0.0;
233 progress(m_progress, "Processing SplittersWorkspace.");
234 if (m_useSplittersWorkspace) // SplittersWorkspace the class in nanoseconds
236 else if (m_useArbTableSplitters) // TableWorkspace in seconds
238 else
240
241 // Create output workspaces
242 m_progress = 0.1;
243 progress(m_progress, "Create Output Workspaces.");
248 else
250
251 // clone the properties but TimeSeriesProperty
252 std::vector<Kernel::TimeSeriesProperty<int> *> int_tsp_vector;
253 std::vector<Kernel::TimeSeriesProperty<double> *> dbl_tsp_vector;
254 std::vector<Kernel::TimeSeriesProperty<bool> *> bool_tsp_vector;
255 std::vector<Kernel::TimeSeriesProperty<string> *> string_tsp_vector;
256 copyNoneSplitLogs(int_tsp_vector, dbl_tsp_vector, bool_tsp_vector, string_tsp_vector);
257
258 // Optionall import corrections
259 m_progress = 0.20;
260 progress(m_progress, "Importing TOF corrections. ");
262
263 // Filter Events
264 m_progress = 0.30;
265 progress(m_progress, "Filter Events.");
266 double progressamount;
267 if (m_toGroupWS)
268 progressamount = 0.6;
269 else
270 progressamount = 0.7;
271
272 // add a new 'split' tsp to output workspace
273 std::vector<std::unique_ptr<Kernel::TimeSeriesProperty<int>>> split_tsp_vector;
275 filterEventsBySplitters(progressamount);
276 generateSplitterTSPalpha(split_tsp_vector);
277 } else {
278 filterEventsByVectorSplitters(progressamount);
279 generateSplitterTSP(split_tsp_vector);
280 }
281 // assign split_tsp_vector to all the output workspaces!
282 mapSplitterTSPtoWorkspaces(split_tsp_vector);
283
284 // split times series property: new way to split events
285 splitTimeSeriesLogs(int_tsp_vector, dbl_tsp_vector, bool_tsp_vector, string_tsp_vector);
286
287 // Optional to group detector
289
290 // Form the names of output workspaces
291 std::vector<std::string> outputwsnames;
292 Goniometer inputGonio = m_eventWS->run().getGoniometer();
293 for (auto &miter : m_outputWorkspacesMap) {
294 try {
295 DataObjects::EventWorkspace_sptr ws_i = miter.second;
296 ws_i->mutableRun().setGoniometer(inputGonio, true);
297 } catch (std::runtime_error &) {
298 g_log.warning("Cannot set goniometer.");
299 }
300 outputwsnames.emplace_back(miter.second->getName());
301 }
302 setProperty("OutputWorkspaceNames", outputwsnames);
303
304 m_progress = 1.0;
305 progress(m_progress, "Completed");
306}
307
308//----------------------------------------------------------------------------------------------
314 // get event workspace information
315 size_t numhist = m_eventWS->getNumberHistograms();
316 m_vecSkip.resize(numhist, false);
317
318 // check whether any detector is skipped
320 // No TOF correction and skip spectrum only if TOF correction is required
321 g_log.warning("By user's choice, No spectrum will be skipped even if it has "
322 "no detector.");
323 } else {
324 // check detectors whether there is any of them that will be skipped
325 stringstream msgss;
326 size_t numskipspec = 0;
327 size_t numeventsskip = 0;
328
329 const auto &spectrumInfo = m_eventWS->spectrumInfo();
330 for (size_t i = 0; i < numhist; ++i) {
331 if (!spectrumInfo.hasDetectors(i)) {
332 m_vecSkip[i] = true;
333
334 ++numskipspec;
335 const EventList &elist = m_eventWS->getSpectrum(i);
336 numeventsskip += elist.getNumberEvents();
337 msgss << i;
338 if (numskipspec % 10 == 0)
339 msgss << "\n";
340 else
341 msgss << ",";
342 }
343 } // ENDFOR
344
345 if (numskipspec > 0) {
346 g_log.warning() << "There are " << numskipspec << " spectra that do not have detectors. "
347 << "They will be skipped during filtering. There are total " << numeventsskip
348 << " events in those spectra. \nList of these specta is as below:\n"
349 << msgss.str() << "\n";
350 } else {
351 g_log.notice("There is no spectrum that does not have detectors.");
352 }
353
354 } // END-IF-ELSE
355
356 // sort events
358
359 // This runs the SortEvents algorithm in parallel
360 m_eventWS->sortAll(sortType, nullptr);
361
362 return;
363}
364
365//----------------------------------------------------------------------------------------------
369 m_eventWS = this->getProperty("InputWorkspace");
370 if (!m_eventWS) {
371 stringstream errss;
372 errss << "Inputworkspace is not event workspace. ";
373 g_log.error(errss.str());
374 throw std::invalid_argument(errss.str());
375 }
376
377 // Process splitting workspace (table or data)
378 API::Workspace_sptr tempws = this->getProperty("SplitterWorkspace");
379
380 m_splittersWorkspace = std::dynamic_pointer_cast<SplittersWorkspace>(tempws);
381 m_splitterTableWorkspace = std::dynamic_pointer_cast<TableWorkspace>(tempws);
384 } else if (m_splitterTableWorkspace)
386 else {
387 m_matrixSplitterWS = std::dynamic_pointer_cast<MatrixWorkspace>(tempws);
388 if (m_matrixSplitterWS) {
390 } else {
391 throw runtime_error("Invalid type of input workspace, neither "
392 "SplittersWorkspace nor MatrixWorkspace.");
393 }
394 }
395
396 m_informationWS = this->getProperty("InformationWorkspace");
397 // Information workspace is specified?
398 if (!m_informationWS)
399 m_hasInfoWS = false;
400 else
401 m_hasInfoWS = true;
402
403 m_outputWSNameBase = this->getPropertyValue("OutputWorkspaceBaseName");
404 m_filterByPulseTime = this->getProperty("FilterByPulseTime");
405
406 m_toGroupWS = this->getProperty("GroupWorkspaces");
407
408 if (m_toGroupWS && (m_outputWSNameBase == m_eventWS->getName())) {
409 std::stringstream errss;
410 errss << "It is not allowed to group output workspaces into the same name "
411 "(i..e, OutputWorkspaceBaseName = "
412 << m_outputWSNameBase << ") as the input workspace to filter events from.";
413 throw std::invalid_argument(errss.str());
414 }
415
416 //-------------------------------------------------------------------------
417 // TOF detector/sample correction
418 //-------------------------------------------------------------------------
419 // Type of correction
420 string correctiontype = getPropertyValue("CorrectionToSample");
421 if (correctiontype == "None")
423 else if (correctiontype == "Customized")
425 else if (correctiontype == "Direct")
427 else if (correctiontype == "Elastic")
429 else if (correctiontype == "Indirect")
431 else {
432 g_log.error() << "Correction type '" << correctiontype << "' is not supported. \n";
433 throw runtime_error("Impossible situation!");
434 }
435
436 // Spectrum skip
437 string skipappr = getPropertyValue("SpectrumWithoutDetector");
438 if (skipappr == "Skip")
440 else if (skipappr == "Skip only if TOF correction")
442 else
443 throw runtime_error("An unrecognized option for SpectrumWithoutDetector");
444 m_splitSampleLogs = getProperty("SplitSampleLogs");
445
446 // Debug spectrum
447 m_dbWSIndex = getProperty("DBSpectrum");
448 if (isEmpty(m_dbWSIndex))
449 m_useDBSpectrum = false;
450 else
451 m_useDBSpectrum = true;
452
453 bool start_time_set = false;
454 // Get run start time
455 try {
456 m_runStartTime = m_eventWS->run().startTime();
457 start_time_set = true;
458 } catch (std::runtime_error &) {
459 }
460
461 // Splitters are given relative time
462 m_isSplittersRelativeTime = getProperty("RelativeTime");
464 // Using relative time
465 std::string start_time_str = getProperty("FilterStartTime");
466 if (!start_time_str.empty()) {
467 // User specifies the filter starting time
468 Types::Core::DateAndTime temp_shift_time(start_time_str);
469 m_filterStartTime = temp_shift_time;
470 } else {
471 // Retrieve filter starting time from property run_start as default
472 if (start_time_set) {
474 } else {
475 throw std::runtime_error("Input event workspace does not have property run_start. "
476 "User does not specifiy filter start time."
477 "Splitters cannot be in reltive time.");
478 }
479 }
480 } // END-IF: m_isSplitterRelativeTime
481}
482
483//----------------------------------------------------------------------------------------------
488 // return if there is no such need
489 if (!m_toGroupWS)
490 return;
491
492 // set progress
493 m_progress = 0.95;
494 progress(m_progress, "Group workspaces");
495
496 std::string groupname = m_outputWSNameBase;
497 auto groupws = createChildAlgorithm("GroupWorkspaces", 0.95, 1.00, true);
498 groupws->setAlwaysStoreInADS(true);
499 groupws->setProperty("InputWorkspaces", m_wsNames);
500 groupws->setProperty("OutputWorkspace", groupname);
501 groupws->execute();
502 if (!groupws->isExecuted()) {
503 g_log.error("Grouping all output workspaces fails.");
504 return;
505 }
506
507 // set the group workspace as output workspace
508 if (!this->existsProperty("OutputWorkspace")) {
510 std::make_unique<WorkspaceProperty<WorkspaceGroup>>("OutputWorkspace", groupname, Direction::Output),
511 "Name of the workspace to be created as the output of grouping ");
512 }
513
515 API::WorkspaceGroup_sptr workspace_group = std::dynamic_pointer_cast<WorkspaceGroup>(ads.retrieve(groupname));
516 if (!workspace_group) {
517 g_log.error("Unable to retrieve output workspace from algorithm GroupWorkspaces");
518 return;
519 }
520 setProperty("OutputWorkspace", workspace_group);
521
522 return;
523}
524
525//----------------------------------------------------------------------------------------------
536void FilterEvents::copyNoneSplitLogs(std::vector<TimeSeriesProperty<int> *> &int_tsp_name_vector,
537 std::vector<TimeSeriesProperty<double> *> &dbl_tsp_name_vector,
538 std::vector<TimeSeriesProperty<bool> *> &bool_tsp_name_vector,
539 std::vector<Kernel::TimeSeriesProperty<string> *> &string_tsp_vector) {
540 // get the user input information
541 bool exclude_listed_logs = getProperty("ExcludeSpecifiedLogs");
542 std::vector<std::string> tsp_logs = getProperty("TimeSeriesPropertyLogs");
543 // convert to set
544 std::set<std::string> tsp_logs_set(tsp_logs.begin(), tsp_logs.end());
545
546 std::set<std::string>::iterator set_iter;
547 // initialize
548 int_tsp_name_vector.clear();
549 dbl_tsp_name_vector.clear();
550 bool_tsp_name_vector.clear();
551
552 std::vector<Property *> prop_vector = m_eventWS->run().getProperties();
553 for (auto *prop_i : prop_vector) {
554 // get property
555 std::string name_i = prop_i->name();
556
557 // cast to different type of TimeSeriesProperties
558 auto *dbl_prop = dynamic_cast<TimeSeriesProperty<double> *>(prop_i);
559 auto *int_prop = dynamic_cast<TimeSeriesProperty<int> *>(prop_i);
560 auto *bool_prop = dynamic_cast<TimeSeriesProperty<bool> *>(prop_i);
561 auto *string_prop = dynamic_cast<TimeSeriesProperty<string> *>(prop_i);
562
563 // check for time series properties
564 if (dbl_prop || int_prop || bool_prop || string_prop) {
565 // check whether the log is there
566 set_iter = tsp_logs_set.find(name_i);
567 if (exclude_listed_logs && set_iter != tsp_logs_set.end()) {
568 // exclude all the listed tsp logs and this log name is in the set
569 // skip
570 g_log.warning() << "Skip splitting sample log " << name_i << "\n";
571 continue;
572 } else if (!exclude_listed_logs && set_iter == tsp_logs_set.end()) {
573 // include all the listed tsp logs to split but this log name is NOT in
574 // the set
575 // skip
576 g_log.warning() << "Skip splitting sample log " << name_i << "\n";
577 continue;
578 }
579
580 // insert the time series property to proper target vector
581 if (dbl_prop) {
582 // is double time series property
583 dbl_tsp_name_vector.emplace_back(dbl_prop);
584 } else if (int_prop) {
585 // is integer time series property
586 int_tsp_name_vector.emplace_back(int_prop);
587 } else if (bool_prop) {
588 // is integer time series property
589 bool_tsp_name_vector.emplace_back(bool_prop);
590 continue;
591 } else if (string_prop) {
592 // is string time series property
593 string_tsp_vector.emplace_back(string_prop);
594 }
595
596 } else {
597 // non time series properties
598 // single value property: copy to the new workspace
599 std::map<int, DataObjects::EventWorkspace_sptr>::iterator ws_iter;
600 for (ws_iter = m_outputWorkspacesMap.begin(); ws_iter != m_outputWorkspacesMap.end(); ++ws_iter) {
601
602 std::string value_i = prop_i->value();
603 double double_v;
604 int int_v;
605 if (Strings::convert(value_i, double_v) != 0) // double value
606 ws_iter->second->mutableRun().addProperty(name_i, double_v, true);
607 else if (Strings::convert(value_i, int_v) != 0)
608 ws_iter->second->mutableRun().addProperty(name_i, int_v, true);
609 else
610 ws_iter->second->mutableRun().addProperty(name_i, value_i, true);
611 }
612 }
613 } // end for
614
615 return;
616}
617
618//----------------------------------------------------------------------------------------------
626void FilterEvents::splitTimeSeriesLogs(const std::vector<TimeSeriesProperty<int> *> &int_tsp_vector,
627 const std::vector<TimeSeriesProperty<double> *> &dbl_tsp_vector,
628 const std::vector<TimeSeriesProperty<bool> *> &bool_tsp_vector,
629 const std::vector<TimeSeriesProperty<string> *> &string_tsp_vector) {
630 // get split times by converting vector of int64 to Time
631 std::vector<Types::Core::DateAndTime> split_datetime_vec;
632
633 // convert splitters workspace to vectors used by TableWorkspace and
634 // MatrixWorkspace splitters
637 }
638
639 // convert splitter time vector to DateAndTime format
640 split_datetime_vec.resize(m_vecSplitterTime.size());
641 for (size_t i = 0; i < m_vecSplitterTime.size(); ++i) {
642 DateAndTime split_time(m_vecSplitterTime[i]);
643 split_datetime_vec[i] = split_time;
644 }
645
646 // find the maximum index of the outputs' index
647 std::set<int>::iterator target_iter;
648 int max_target_index = 0;
649 for (target_iter = m_targetWorkspaceIndexSet.begin(); target_iter != m_targetWorkspaceIndexSet.end(); ++target_iter) {
650 if (*target_iter > max_target_index)
651 max_target_index = *target_iter;
652 }
653 g_log.information() << "Maximum target index = " << max_target_index << "\n";
654
655 // splitters workspace need to have 1 more for left-over events
657 ++max_target_index;
658
659 // deal with integer time series property
660 for (const auto &int_tsp : int_tsp_vector) {
661 splitTimeSeriesProperty(int_tsp, split_datetime_vec, max_target_index);
662 }
663
664 // split double time series property
665 for (const auto &dbl_tsp : dbl_tsp_vector) {
666 splitTimeSeriesProperty(dbl_tsp, split_datetime_vec, max_target_index);
667 }
668
669 // deal with bool time series property
670 for (const auto &bool_tsp : bool_tsp_vector) {
671 splitTimeSeriesProperty(bool_tsp, split_datetime_vec, max_target_index);
672 }
673
674 // deal with string time series property
675 for (const auto &string_tsp : string_tsp_vector) {
676 splitTimeSeriesProperty(string_tsp, split_datetime_vec, max_target_index);
677 }
678
679 // integrate proton charge
680 for (int tindex = 0; tindex <= max_target_index; ++tindex) {
681 // find output workspace
682 std::map<int, DataObjects::EventWorkspace_sptr>::iterator wsiter;
683 wsiter = m_outputWorkspacesMap.find(tindex);
684 if (wsiter == m_outputWorkspacesMap.end()) {
685 g_log.information() << "Workspace target (indexed as " << tindex << ") does not have workspace associated.\n";
686 } else {
687 DataObjects::EventWorkspace_sptr ws_i = wsiter->second;
688 if (ws_i->run().hasProperty("proton_charge")) {
689 ws_i->mutableRun().integrateProtonCharge();
690 }
691 }
692 }
693
694 return;
695}
696
697//----------------------------------------------------------------------------------------------
704template <typename TYPE>
706 std::vector<Types::Core::DateAndTime> &split_datetime_vec,
707 const int max_target_index) {
708 // skip the sample logs if they are specified
709 // get property name and etc
710 const std::string &property_name = tsp->name();
711 // generate new propertys for the source to split to
712 std::vector<std::unique_ptr<TimeSeriesProperty<TYPE>>> output_vector;
713 for (int tindex = 0; tindex <= max_target_index; ++tindex) {
714 auto new_property = std::make_unique<TimeSeriesProperty<TYPE>>(property_name);
715 new_property->setUnits(tsp->units());
716 output_vector.emplace_back(std::move(new_property));
717 }
718
719 // duplicate the time series property if the size is just one
720 if (tsp->size() == 1) {
721 // duplicate
722 for (size_t i_out = 0; i_out < output_vector.size(); ++i_out) {
723 output_vector[i_out]->addValue(tsp->firstTime(), tsp->firstValue());
724 }
725 } else {
726 // split log
727 std::vector<TimeSeriesProperty<TYPE> *> split_properties(output_vector.size());
728 // use vector of raw pointers for splitting
729 std::transform(output_vector.begin(), output_vector.end(), split_properties.begin(),
730 [](const std::unique_ptr<TimeSeriesProperty<TYPE>> &x) { return x.get(); });
731 tsp->splitByTimeVector(split_datetime_vec, m_vecSplitterGroup, split_properties);
732 }
733
734 // assign to output workspaces
735 for (int tindex = 0; tindex <= max_target_index; ++tindex) {
736 // find output workspace
737 auto wsiter = m_outputWorkspacesMap.find(tindex);
738 if (wsiter == m_outputWorkspacesMap.end()) {
739 // unable to find workspace associated with target index
740 g_log.information() << "Workspace target (" << tindex << ") does not have workspace associated."
741 << "\n";
742 } else {
743 // add property to the associated workspace
744 DataObjects::EventWorkspace_sptr ws_i = wsiter->second;
745 ws_i->mutableRun().addProperty(std::move(output_vector[tindex]), true);
746 }
747 }
748
749 return;
750}
751
752//----------------------------------------------------------------------------------------------
762 // 1. Init data structure
763 size_t numsplitters = m_splittersWorkspace->getNumberSplitters();
764 m_splitters.reserve(numsplitters);
765
766 // 2. Insert all splitters
768 bool inorder = true;
769 for (size_t i = 0; i < numsplitters; i++) {
770 // push back the splitter in SplittersWorkspace to list of splitters
771 m_splitters.emplace_back(m_splittersWorkspace->getSplitter(i));
772 // add the target workspace index to target workspace indexes set
773 m_targetWorkspaceIndexSet.insert(m_splitters.back().index());
774 // register for the maximum target index
775 if (m_splitters.back().index() > m_maxTargetIndex)
776 m_maxTargetIndex = m_splitters.back().index();
777 // check whether the splitters are in time order
778 if (inorder && i > 0 && m_splitters[i] < m_splitters[i - 1])
779 inorder = false;
780 }
781 m_progress = 0.05;
783
784 // 3. Order if not ordered and add workspace for events excluded
785 if (!inorder) {
786 std::sort(m_splitters.begin(), m_splitters.end());
787 }
788
789 // 4. Add extra workgroup index for unfiltered events
790 m_targetWorkspaceIndexSet.insert(-1);
791
792 // 5. Add information
793 if (m_hasInfoWS) {
794 if (m_targetWorkspaceIndexSet.size() > m_informationWS->rowCount() + 1) {
795 g_log.warning() << "Input Splitters Workspace has different entries (" << m_targetWorkspaceIndexSet.size() - 1
796 << ") than input information workspaces (" << m_informationWS->rowCount() << "). "
797 << " Information may not be accurate. \n";
798 }
799 }
800}
801
802//----------------------------------------------------------------------------------------------
810 // check: only applied for splitters given by SplittersWorkspace
812
813 // clear and get ready
814 m_vecSplitterGroup.clear();
815 m_vecSplitterTime.clear();
816
817 // define filter-left target index
818 int no_filter_index = m_maxTargetIndex + 1;
819
820 // convert SplittersWorkspace to a set of pairs which can be sorted
821 size_t num_splitters = m_splitters.size();
822 int64_t last_entry_time(0);
823
824 // it is assumed that m_splitters is sorted by time
825 for (size_t i_splitter = 0; i_splitter < num_splitters; ++i_splitter) {
826 // get splitter
827 Kernel::SplittingInterval splitter = m_splitters[i_splitter];
828 int64_t start_time_i64 = splitter.start().totalNanoseconds();
829 int64_t stop_time_i64 = splitter.stop().totalNanoseconds();
830 if (m_vecSplitterTime.empty()) {
831 // first entry: add
832 m_vecSplitterTime.emplace_back(start_time_i64);
833 m_vecSplitterTime.emplace_back(stop_time_i64);
834 m_vecSplitterGroup.emplace_back(splitter.index());
835 } else if (abs(last_entry_time - start_time_i64) < TOLERANCE) {
836 // start time is SAME as last entry
837 m_vecSplitterTime.emplace_back(stop_time_i64);
838 m_vecSplitterGroup.emplace_back(splitter.index());
839 } else if (start_time_i64 > last_entry_time + TOLERANCE) {
840 // start time is way behind. then add an empty one
841 m_vecSplitterTime.emplace_back(start_time_i64);
842 m_vecSplitterTime.emplace_back(stop_time_i64);
843 m_vecSplitterGroup.emplace_back(no_filter_index);
844 m_vecSplitterGroup.emplace_back(splitter.index());
845 } else {
846 // some impossible situation
847 std::stringstream errorss;
848 errorss << "New start time " << start_time_i64 << " is before last entry's time " << last_entry_time;
849 throw std::runtime_error(errorss.str());
850 }
851
852 // update
853 last_entry_time = m_vecSplitterTime.back();
854 } // END-FOR (add all splitters)
855
856 return;
857}
858
859//----------------------------------------------------------------------------------------------
879 // Check input workspace validity
880 assert(m_matrixSplitterWS);
881
882 const auto X = m_matrixSplitterWS->binEdges(0);
883 const auto &Y = m_matrixSplitterWS->y(0);
884 const size_t sizex = X.size();
885 const size_t sizey = Y.size();
886
887 // Assign vectors for time comparison
888 m_vecSplitterTime.assign(sizex, static_cast<int64_t>(0));
889 m_vecSplitterGroup.assign(sizey, static_cast<int>(-1));
890
891 // Transform vector
892 for (size_t i = 0; i < sizex; ++i) {
893 m_vecSplitterTime[i] = static_cast<int64_t>(X[i] * 1.E9);
894 }
895
896 // shift the splitters' time if user specifis that the input times are
897 // relative
899 const int64_t time_shift_ns = m_filterStartTime.totalNanoseconds();
900 for (size_t i = 0; i < sizex; ++i)
901 m_vecSplitterTime[i] += time_shift_ns;
902 }
903
904 // process the group
905 uint32_t max_target_index = 1;
906
907 for (size_t i = 0; i < sizey; ++i) {
908
909 auto y_index = static_cast<int>(Y[i]);
910
911 // try to find Y[i] in m_yIndexMap
912 auto mapiter = m_yIndexMap.find(y_index);
913 if (mapiter == m_yIndexMap.end()) {
914 // new
915 // default to 0 as undefined slot.
916 uint32_t int_target = UNDEFINED_SPLITTING_TARGET;
917 // if well-defined, then use the current
918 if (y_index >= 0) {
919 int_target = max_target_index;
920 ++max_target_index;
921 }
922
923 // un-defined or un-filtered
924 m_vecSplitterGroup[i] = int_target;
925
926 // add to maps and etc.
927 m_yIndexMap.emplace(y_index, int_target);
928 m_wsGroupdYMap.emplace(int_target, y_index);
929 m_targetWorkspaceIndexSet.insert(int_target);
930 } else {
931 // this target Y-index has been registered previously
932 uint32_t target_index = mapiter->second;
933 m_vecSplitterGroup[i] = target_index;
934 }
935 }
936
937 // register the max target integer
938 m_maxTargetIndex = max_target_index - 1;
939
940 return;
941}
942
943namespace {
944// offset_ns - an offset from the GPS epoch
945int64_t timeInSecondsToNanoseconds(const int64_t offset_ns, const double time_sec) {
946 return offset_ns + static_cast<int64_t>(time_sec * 1.E9);
947}
948} // anonymous namespace
949
950//----------------------------------------------------------------------------------------------
960 // check input workspace's validity
962 if (m_splitterTableWorkspace->columnCount() != 3) {
963 throw std::runtime_error("Splitters given in TableWorkspace must have 3 columns.");
964 }
965
966 // clear vector splitterTime and vector of splitter group
967 m_vecSplitterTime.clear();
968 m_vecSplitterGroup.clear();
969 bool found_undefined_splitter = false;
970
971 // get the run start time
972 int64_t filter_shift_time(0);
974 filter_shift_time = m_runStartTime.totalNanoseconds();
975
976 int max_target_index = 1;
977
978 // convert TableWorkspace's values to vectors
979 size_t num_rows = m_splitterTableWorkspace->rowCount();
980 for (size_t irow = 0; irow < num_rows; ++irow) {
981 // get start and stop time in second
982 const auto start_time =
983 timeInSecondsToNanoseconds(filter_shift_time, m_splitterTableWorkspace->cell_cast<double>(irow, 0));
984 const auto stop_time =
985 timeInSecondsToNanoseconds(filter_shift_time, m_splitterTableWorkspace->cell_cast<double>(irow, 1));
986 const auto target = m_splitterTableWorkspace->cell<std::string>(irow, 2);
987
988 if (m_vecSplitterTime.empty()) {
989 // first splitter: push the start time to vector
990 m_vecSplitterTime.emplace_back(start_time);
991 } else if (start_time - m_vecSplitterTime.back() > TOLERANCE) {
992 // the start time is way behind previous splitter's stop time
993 // create a new splitter and set the time interval in the middle to target
994 // -1
995 m_vecSplitterTime.emplace_back(start_time);
996 // NOTE: use index = 0 for un-defined slot
998 found_undefined_splitter = true;
999 } else if (abs(start_time - m_vecSplitterTime.back()) < TOLERANCE) {
1000 // new splitter's start time is same (within tolerance) as the stop time
1001 // of the previous
1002 ;
1003 } else {
1004 // new splitter's start time is before the stop time of the last splitter.
1005 throw std::runtime_error("Input table workspace does not have splitters "
1006 "set up in order, which is a requirement.");
1007 }
1008
1009 // convert string-target to integer target
1010 const auto &mapiter = m_targetIndexMap.find(target);
1011
1012 int int_target;
1013 if (mapiter != m_targetIndexMap.end()) {
1014 int_target = mapiter->second;
1015 } else {
1016 // target is not in map
1017 int_target = max_target_index;
1018 m_targetIndexMap.insert(std::pair<std::string, int>(target, int_target));
1019 m_wsGroupIndexTargetMap.emplace(int_target, target);
1020 this->m_targetWorkspaceIndexSet.insert(int_target);
1021 max_target_index++;
1022 }
1023
1024 // add start time, stop time and 'target
1025 m_vecSplitterTime.emplace_back(stop_time);
1026 m_vecSplitterGroup.emplace_back(int_target);
1027 } // END-FOR (irow)
1028
1029 // record max target index
1030 m_maxTargetIndex = max_target_index - 1;
1031
1032 // add un-defined splitter to map
1033 if (found_undefined_splitter) {
1034 m_targetIndexMap.emplace("undefined", 0);
1035 m_wsGroupIndexTargetMap.emplace(0, "undefined");
1036 m_targetWorkspaceIndexSet.insert(0);
1037 }
1038
1039 return;
1040}
1041
1042//----------------------------------------------------------------------------------------------
1048 const auto startTime = std::chrono::high_resolution_clock::now();
1049
1050 // Convert information workspace to map
1051 std::map<int, std::string> infomap;
1052 if (m_hasInfoWS) {
1053 for (size_t ir = 0; ir < m_informationWS->rowCount(); ++ir) {
1054 API::TableRow row = m_informationWS->getRow(ir);
1055 infomap.emplace(row.Int(0), row.String(1));
1056 }
1057 }
1058
1059 // Determine the minimum group index number
1060 const int minwsgroup = *std::min_element(m_targetWorkspaceIndexSet.begin(), m_targetWorkspaceIndexSet.end(),
1061 [](const int &left, const int &right) {
1062 if (left >= 0 && right >= 0)
1063 return left < right;
1064 if (left >= 0)
1065 return true;
1066 else
1067 return false;
1068 });
1069 g_log.debug() << "Min WS Group = " << minwsgroup << "\n";
1070
1071 const bool from1 = getProperty("OutputWorkspaceIndexedFrom1");
1072 int delta_wsindex = 0;
1073 if (from1) {
1074 delta_wsindex = 1 - minwsgroup;
1075 }
1076
1077 // Set up new workspaces
1078 int numoutputws = 0;
1079 auto numnewws = static_cast<double>(m_targetWorkspaceIndexSet.size());
1080 double wsgindex = 0.;
1081
1082 // Work out how it has been split so the naming can be done
1083 // if generateEventsFilter has been used the infoWS will contain time or log
1084 // otherwise it is assumed that it has been split by time.
1085 bool descriptiveNames = getProperty("DescriptiveOutputNames");
1086 bool splitByTime = true;
1087 if (descriptiveNames) {
1088 if ((m_hasInfoWS && infomap[0].find("Log") != std::string::npos) ||
1089 m_targetWorkspaceIndexSet.size() - 1 != m_splitters.size()) {
1090 splitByTime = false;
1091 }
1092 }
1093 std::shared_ptr<EventWorkspace> prototype_ws = create<EventWorkspace>(*m_eventWS);
1094
1095 for (auto const wsgroup : m_targetWorkspaceIndexSet) {
1096 // Generate new workspace name
1097 bool add2output = true;
1098 std::stringstream wsname;
1099 wsname << m_outputWSNameBase << "_";
1100 if (wsgroup >= 0) {
1101 if (descriptiveNames && splitByTime) {
1102 auto splitter = m_splitters[wsgroup];
1103 auto startTimeInSeconds =
1104 Mantid::Types::Core::DateAndTime::secondsFromDuration(splitter.start() - m_runStartTime);
1105 auto stopTimeInSeconds =
1106 Mantid::Types::Core::DateAndTime::secondsFromDuration(splitter.stop() - m_runStartTime);
1107 wsname << startTimeInSeconds << "_" << stopTimeInSeconds;
1108 } else if (descriptiveNames) {
1109 auto infoiter = infomap.find(wsgroup);
1110 if (infoiter != infomap.end()) {
1111 std::string name = infoiter->second;
1113 wsname << name;
1114 } else {
1115 wsname << wsgroup + delta_wsindex;
1116 }
1117 } else {
1118 wsname << wsgroup + delta_wsindex;
1119 }
1120 } else {
1121 wsname << "unfiltered";
1122 if (from1)
1123 add2output = false;
1124 }
1125
1126 std::shared_ptr<EventWorkspace> optws = prototype_ws->clone();
1127 // Clear Run without copying first.
1128 optws->setSharedRun(Kernel::make_cow<Run>());
1129 m_outputWorkspacesMap.emplace(wsgroup, optws);
1130
1131 // Add information, including title and comment, to output workspace
1132 if (m_hasInfoWS) {
1133 std::string info;
1134 if (wsgroup < 0) {
1135 info = "Events that are filtered out. ";
1136 } else {
1137 std::map<int, std::string>::iterator infoiter;
1138 infoiter = infomap.find(wsgroup);
1139 if (infoiter != infomap.end()) {
1140 info = infoiter->second;
1141 } else {
1142 info = "This workspace has no information provided. ";
1143 }
1144 }
1145 optws->setComment(info);
1146 optws->setTitle(info);
1147 } // END-IF infor WS
1148
1149 // Add to output properties. There shouldn't be any workspace
1150 // (non-unfiltered) skipped from group index
1151 if (add2output) {
1152 // Generate output property name
1153 std::stringstream propertynamess;
1154 if (wsgroup == -1) {
1155 propertynamess << "OutputWorkspace_unfiltered";
1156 } else {
1157 propertynamess << "OutputWorkspace_" << wsgroup;
1158 }
1159
1160 // Inserted this pair to map
1161 m_wsNames.emplace_back(wsname.str());
1162
1163 // Set (property) to output workspace and set to ADS
1164 AnalysisDataService::Instance().addOrReplace(wsname.str(), optws);
1165
1166 // create these output properties
1167 if (!this->m_toGroupWS) {
1168 if (!this->existsProperty(propertynamess.str())) {
1170 propertynamess.str(), wsname.str(), Direction::Output),
1171 "Output");
1172 }
1173 setProperty(propertynamess.str(), optws);
1174 }
1175
1176 ++numoutputws;
1177 g_log.debug() << "Created output Workspace of group = " << wsgroup << " Property Name = " << propertynamess.str()
1178 << " Workspace name = " << wsname.str() << " with Number of events = " << optws->getNumberEvents()
1179 << "\n";
1180
1181 // Update progress report
1182 m_progress = 0.1 + 0.1 * wsgindex / numnewws;
1183 progress(m_progress, "Creating output workspace");
1184 wsgindex += 1.;
1185 } // If add workspace to output
1186
1187 } // ENDFOR
1188
1189 setProperty("NumberOutputWS", numoutputws);
1190 addTimer("createOutputWorkspacesSplitters", startTime, std::chrono::high_resolution_clock::now());
1191
1192 g_log.information("Output workspaces are created. ");
1193} // namespace Algorithms
1194
1195//----------------------------------------------------------------------------------------------
1205 // check condition
1206 if (!m_matrixSplitterWS) {
1207 g_log.error("createOutputWorkspacesMatrixCase() is applied to "
1208 "MatrixWorkspace splitters only!");
1209 throw std::runtime_error("Wrong call!");
1210 }
1211
1212 // set up new workspaces
1213 // Note: m_targetWorkspaceIndexSet is used in different manner among
1214 // SplittersWorkspace, MatrixWorkspace and TableWorkspace cases
1215 size_t numoutputws = m_targetWorkspaceIndexSet.size();
1216 size_t wsgindex = 0;
1217 bool descriptiveNames = getProperty("DescriptiveOutputNames");
1218
1219 std::shared_ptr<EventWorkspace> prototype_ws = create<EventWorkspace>(*m_eventWS);
1220
1221 for (auto const wsgroup : m_targetWorkspaceIndexSet) {
1222 if (wsgroup < 0)
1223 throw std::runtime_error("It is not possible to have split-target group "
1224 "index < 0 in MatrixWorkspace case.");
1225
1226 // workspace name
1227 std::stringstream wsname;
1228 if (wsgroup > 0) {
1229 if (descriptiveNames) {
1230 auto startTime = m_vecSplitterTime[wsgroup];
1231 auto stopTime = m_vecSplitterTime[wsgroup + 1];
1232 wsname << m_outputWSNameBase << "_" << startTime << "_" << stopTime;
1233 } else {
1234 int target_name = m_wsGroupdYMap[wsgroup];
1235 wsname << m_outputWSNameBase << "_" << target_name;
1236 }
1237 } else {
1238 wsname << m_outputWSNameBase << "_unfiltered";
1239 }
1240
1241 // create new workspace from input EventWorkspace and all the sample logs
1242 // are copied to the new one
1243 std::shared_ptr<EventWorkspace> optws = prototype_ws->clone();
1244 // Clear Run without copying first.
1245 optws->setSharedRun(Kernel::make_cow<Run>());
1246 m_outputWorkspacesMap.emplace(wsgroup, optws);
1247
1248 // add to output workspace property
1249 std::stringstream propertynamess;
1250 if (wsgroup == 0) {
1251 propertynamess << "OutputWorkspace_unfiltered";
1252 } else {
1253 propertynamess << "OutputWorkspace_" << wsgroup;
1254 }
1255
1256 // Inserted this pair to map
1257 m_wsNames.emplace_back(wsname.str());
1258 AnalysisDataService::Instance().addOrReplace(wsname.str(), optws);
1259
1260 g_log.debug() << "Created output Workspace of group = " << wsgroup << " Workspace name = " << wsname.str()
1261 << " with Number of events = " << optws->getNumberEvents() << "\n";
1262
1263 // Set (property) to output workspace and set to ADS
1264 if (m_toGroupWS) {
1265 if (!this->existsProperty(propertynamess.str())) {
1267 propertynamess.str(), wsname.str(), Direction::Output),
1268 "Output");
1269 }
1270 setProperty(propertynamess.str(), optws);
1271
1272 g_log.debug() << " Property Name = " << propertynamess.str() << "\n";
1273 } else {
1274 g_log.debug() << "\n";
1275 }
1276
1277 // Update progress report
1278 m_progress = 0.1 + 0.1 * static_cast<double>(wsgindex) / static_cast<double>(numoutputws);
1279 progress(m_progress, "Creating output workspace");
1280 wsgindex += 1;
1281 } // END-FOR (wsgroup)
1282
1283 // Set output and do debug report
1284 g_log.debug() << "Output workspace number: " << numoutputws << "\n";
1285 setProperty("NumberOutputWS", static_cast<int>(numoutputws));
1286
1287 return;
1288}
1289
1290//----------------------------------------------------------------------------------------------
1300 // check condition
1302 g_log.error("createOutputWorkspacesTableSplitterCase() is applied to "
1303 "TableWorkspace splitters only!");
1304 throw std::runtime_error("Wrong call!");
1305 }
1306
1307 // set up new workspaces
1308 size_t numoutputws = m_targetWorkspaceIndexSet.size();
1309 size_t wsgindex = 0;
1310
1311 std::shared_ptr<EventWorkspace> prototype_ws = create<EventWorkspace>(*m_eventWS);
1312
1313 for (auto const wsgroup : m_targetWorkspaceIndexSet) {
1314 if (wsgroup < 0)
1315 throw std::runtime_error("It is not possible to have split-target group "
1316 "index < 0 in TableWorkspace case.");
1317
1318 // workspace name
1319 std::stringstream wsname;
1320 bool descriptiveNames = getProperty("DescriptiveOutputNames");
1321
1322 if (wsgroup > 0) {
1323 if (descriptiveNames) {
1324 size_t startIndex = 0;
1325 for (size_t itr = 0; itr < m_vecSplitterGroup.size(); ++itr) {
1326 if (m_vecSplitterGroup[itr] == wsgroup)
1327 startIndex = itr;
1328 }
1329 auto startTime = static_cast<double>(m_vecSplitterTime[startIndex] - m_runStartTime.totalNanoseconds()) / 1.E9;
1330 auto stopTime =
1331 static_cast<double>(m_vecSplitterTime[startIndex + 1] - m_runStartTime.totalNanoseconds()) / 1.E9;
1332 wsname << m_outputWSNameBase << "_" << startTime << "_" << stopTime;
1333 } else {
1334 std::string target_name = m_wsGroupIndexTargetMap[wsgroup];
1335 wsname << m_outputWSNameBase << "_" << target_name;
1336 }
1337 } else {
1338 wsname << m_outputWSNameBase << "_unfiltered";
1339 }
1340
1341 // create new workspace
1342 std::shared_ptr<EventWorkspace> optws = prototype_ws->clone();
1343 // Clear Run without copying first.
1344 optws->setSharedRun(Kernel::make_cow<Run>());
1345 m_outputWorkspacesMap.emplace(wsgroup, optws);
1346
1347 // TODO/NOW/ISSUE -- How about comment and info?
1348
1349 // add to output workspace property
1350
1351 // Inserted this pair to map
1352 m_wsNames.emplace_back(wsname.str());
1353
1354 // Set (property) to output workspace and set to ADS
1355 AnalysisDataService::Instance().addOrReplace(wsname.str(), optws);
1356
1357 g_log.debug() << "Created output Workspace of group = " << wsgroup << " Workspace name = " << wsname.str()
1358 << " with Number of events = " << optws->getNumberEvents() << "\n";
1359
1360 if (this->m_toGroupWS) {
1361 std::stringstream propertynamess;
1362 if (wsgroup < 0) {
1363 propertynamess << "OutputWorkspace_unfiltered";
1364 } else {
1365 propertynamess << "OutputWorkspace_" << wsgroup;
1366 }
1367 if (!this->existsProperty(propertynamess.str())) {
1369 propertynamess.str(), wsname.str(), Direction::Output),
1370 "Output");
1371 }
1372 setProperty(propertynamess.str(), optws);
1373
1374 g_log.debug() << " Property Name = " << propertynamess.str() << "\n";
1375 } else {
1376 g_log.debug() << "\n";
1377 }
1378
1379 // Update progress report
1380 m_progress = 0.1 + 0.1 * static_cast<double>(wsgindex) / static_cast<double>(numoutputws);
1381 progress(m_progress, "Creating output workspace");
1382 wsgindex += 1;
1383 } // END-FOR (wsgroup)
1384
1385 // Set output and do debug report
1386 g_log.debug() << "Output workspace number: " << numoutputws << "\n";
1387 setProperty("NumberOutputWS", static_cast<int>(numoutputws));
1388
1389 return;
1390}
1391
1399 // Set output correction workspace and set to output
1400 const size_t numhist = m_eventWS->getNumberHistograms();
1401 MatrixWorkspace_sptr corrws = create<Workspace2D>(numhist, Points(2));
1402 setProperty("OutputTOFCorrectionWorkspace", corrws);
1403
1404 // Set up the size of correction and output correction workspace
1405 m_detTofOffsets.resize(numhist, 0.0); // unit of TOF
1406 m_detTofFactors.resize(numhist, 1.0); // multiplication factor
1407
1408 // Set up detector values
1409 std::unique_ptr<TimeAtSampleStrategy> strategy;
1410
1413 } else if (m_tofCorrType == ElasticCorrect) {
1414 // Generate TOF correction from instrument's set up
1415 strategy.reset(setupElasticTOFCorrection());
1416 } else if (m_tofCorrType == DirectCorrect) {
1417 // Generate TOF correction for direct inelastic instrument
1418 strategy.reset(setupDirectTOFCorrection());
1419 } else if (m_tofCorrType == IndirectCorrect) {
1420 // Generate TOF correction for indirect elastic instrument
1421 strategy.reset(setupIndirectTOFCorrection());
1422 }
1423 if (strategy) {
1424 for (size_t i = 0; i < numhist; ++i) {
1425 if (!m_vecSkip[i]) {
1426
1427 Correction correction = strategy->calculate(i);
1428 m_detTofOffsets[i] = correction.offset;
1429 m_detTofFactors[i] = correction.factor;
1430
1431 corrws->mutableY(i)[0] = correction.factor;
1432 corrws->mutableY(i)[1] = correction.offset;
1433 }
1434 }
1435 }
1436}
1437
1439
1441}
1442
1444
1445 // Get incident energy Ei
1446 double ei = getProperty("IncidentEnergy");
1447 if (isEmpty(ei)) {
1448 if (m_eventWS->run().hasProperty("Ei")) {
1449 ei = m_eventWS->run().getLogAsSingleValue("Ei");
1450 g_log.debug() << "Using stored Ei value " << ei << "\n";
1451 } else {
1452 throw std::invalid_argument("No Ei value has been set or stored within the run information.");
1453 }
1454 } else {
1455 g_log.debug() << "Using user-input Ei value " << ei << "\n";
1456 }
1457
1458 return new TimeAtSampleStrategyDirect(m_eventWS, ei);
1459}
1460
1463}
1464
1473 // Check input workspace
1474 m_detCorrectWorkspace = getProperty("DetectorTOFCorrectionWorkspace");
1475 vector<string> colnames = m_detCorrectWorkspace->getColumnNames();
1476 bool hasshift = false;
1477 if (colnames.size() < 2)
1478 throw runtime_error("Input table workspace is not valide.");
1479 else if (colnames.size() >= 3)
1480 hasshift = true;
1481
1482 bool usedetid;
1483 if (colnames[0] == "DetectorID")
1484 usedetid = true;
1485 else if (colnames[0] == "Spectrum")
1486 usedetid = false;
1487 else {
1488 stringstream errss;
1489 errss << "First column must be either DetectorID or Spectrum. " << colnames[0] << " is not supported. ";
1490 throw runtime_error(errss.str());
1491 }
1492
1493 // Parse detector and its TOF correction (i.e., offset factor and tof shift)
1494 // to a map
1495 map<detid_t, double> toffactormap;
1496 map<detid_t, double> tofshiftmap;
1497 size_t numrows = m_detCorrectWorkspace->rowCount();
1498 for (size_t i = 0; i < numrows; ++i) {
1499 TableRow row = m_detCorrectWorkspace->getRow(i);
1500
1501 // Parse to map
1502 detid_t detid;
1503 double offset_factor;
1504 row >> detid >> offset_factor;
1505 if (offset_factor >= 0 && offset_factor <= 1) {
1506 // Valid offset (factor value)
1507 toffactormap.emplace(detid, offset_factor);
1508 } else {
1509 // Error, throw!
1510 stringstream errss;
1511 errss << "Correction (i.e., offset) equal to " << offset_factor << " of row "
1512 << "is out of range [0, 1].";
1513 throw runtime_error(errss.str());
1514 }
1515
1516 // Shift
1517 if (hasshift) {
1518 double shift;
1519 row >> shift;
1520 tofshiftmap.emplace(detid, shift);
1521 }
1522 } // ENDFOR(row i)
1523
1524 // Check size of TOF correction map
1525 size_t numhist = m_eventWS->getNumberHistograms();
1526 if (toffactormap.size() > numhist) {
1527 g_log.warning() << "Input correction table workspace has more detectors (" << toffactormap.size()
1528 << ") than input workspace " << m_eventWS->getName() << "'s spectra number (" << numhist << ".\n";
1529 } else if (toffactormap.size() < numhist) {
1530 stringstream errss;
1531 errss << "Input correction table workspace has more detectors (" << toffactormap.size() << ") than input workspace "
1532 << m_eventWS->getName() << "'s spectra number (" << numhist << ".\n";
1533 throw runtime_error(errss.str());
1534 }
1535
1536 // Apply to m_detTofOffsets and m_detTofShifts
1537 if (usedetid) {
1538 // Get vector IDs
1539 vector<detid_t> vecDetIDs(numhist, 0);
1540 // Set up the detector IDs to vecDetIDs and set up the initial value
1541 for (size_t i = 0; i < numhist; ++i) {
1542 // It is assumed that there is one detector per spectra.
1543 // If there are more than 1 spectrum, it is very likely to have problem
1544 // with correction factor
1545 const DataObjects::EventList events = m_eventWS->getSpectrum(i);
1546 const auto &detids = events.getDetectorIDs();
1547 if (detids.size() != 1) {
1548 // Check whether there are more than 1 detector per spectra.
1549 stringstream errss;
1550 errss << "The assumption is that one spectrum has one and only one "
1551 "detector. "
1552 << "Error is found at spectrum " << i << ". It has " << detids.size() << " detectors.";
1553 throw runtime_error(errss.str());
1554 }
1555 vecDetIDs[i] = *detids.begin();
1556 }
1557
1558 // Map correction map to list
1559 map<detid_t, double>::iterator fiter;
1560 for (size_t i = 0; i < numhist; ++i) {
1561 detid_t detid = vecDetIDs[i];
1562 // correction (factor) map
1563 fiter = toffactormap.find(detid);
1564 if (fiter != toffactormap.end())
1565 m_detTofFactors[i] = fiter->second;
1566 else {
1567 stringstream errss;
1568 errss << "Detector "
1569 << "w/ ID << " << detid << " of spectrum " << i << " in Eventworkspace " << m_eventWS->getName()
1570 << " cannot be found in input TOF calibration workspace. ";
1571 throw runtime_error(errss.str());
1572 }
1573 // correction shift map
1574 fiter = tofshiftmap.find(detid);
1575 if (fiter != tofshiftmap.end())
1576 m_detTofOffsets[i] = fiter->second;
1577 } // ENDFOR (each spectrum i)
1578 } else {
1579 // It is spectrum Number already
1580 map<detid_t, double>::iterator fiter;
1581 // correction factor
1582 for (fiter = toffactormap.begin(); fiter != toffactormap.end(); ++fiter) {
1583 auto wsindex = static_cast<size_t>(fiter->first);
1584 if (wsindex < numhist)
1585 m_detTofFactors[wsindex] = fiter->second;
1586 else {
1587 stringstream errss;
1588 errss << "Workspace index " << wsindex << " is out of range.";
1589 throw runtime_error(errss.str());
1590 }
1591 }
1592 // correction shift
1593 for (fiter = tofshiftmap.begin(); fiter != tofshiftmap.end(); ++fiter) {
1594 auto wsindex = static_cast<size_t>(fiter->first);
1595 if (wsindex < numhist)
1596 m_detTofOffsets[wsindex] = fiter->second;
1597 else {
1598 stringstream errss;
1599 errss << "Workspace index " << wsindex << " is out of range.";
1600 throw runtime_error(errss.str());
1601 }
1602 }
1603 }
1604}
1605
1609void FilterEvents::filterEventsBySplitters(double progressamount) {
1610 const auto startTime = std::chrono::high_resolution_clock::now();
1611 size_t numberOfSpectra = m_eventWS->getNumberHistograms();
1612
1613 // Loop over the histograms (detector spectra) to do split from 1 event list
1614 // to N event list
1615 g_log.debug() << "Number of spectra in input/source EventWorkspace = " << numberOfSpectra << ".\n";
1616
1617 // FIXME - Turn on parallel:
1619 for (int64_t iws = 0; iws < int64_t(numberOfSpectra); ++iws) {
1621
1622 // Filter the non-skipped
1623 if (!m_vecSkip[iws]) {
1624 // Get the output event lists (should be empty) to be a map
1625 std::map<int, DataObjects::EventList *> outputs;
1626 PARALLEL_CRITICAL(build_elist) {
1627 for (auto &ws : m_outputWorkspacesMap) {
1628 int index = ws.first;
1629 auto &output_el = ws.second->getSpectrum(iws);
1630 outputs.emplace(index, &output_el);
1631 }
1632 }
1633 // Get a holder on input workspace's event list of this spectrum
1634 const DataObjects::EventList &input_el = m_eventWS->getSpectrum(iws);
1635
1636 // Perform the filtering (using the splitting function and just one
1637 // output)
1638 if (m_filterByPulseTime) {
1639 input_el.splitByPulseTime(m_splitters, outputs);
1640 } else if (m_tofCorrType != NoneCorrect) {
1641 input_el.splitByFullTime(m_splitters, outputs, true, m_detTofFactors[iws], m_detTofOffsets[iws]);
1642 } else {
1643 input_el.splitByFullTime(m_splitters, outputs, false, 1.0, 0.0);
1644 }
1645 }
1646
1648 } // END FOR i = 0
1650
1651 // Split the sample logs in each target workspace.
1652 progress(0.1 + progressamount, "Splitting logs");
1653
1654 addTimer("filterEventsBySplitters", startTime, std::chrono::high_resolution_clock::now());
1655}
1656
1660 size_t numberOfSpectra = m_eventWS->getNumberHistograms();
1661 // FIXME : consider to use vector to index workspace and event list
1662
1663 // Loop over the histograms (detector spectra) to do split from 1 event list
1664 // to N event list
1665 g_log.notice() << "Filter by vector splitters: Number of spectra in "
1666 "input/source EventWorkspace = "
1667 << numberOfSpectra << ".\n";
1668
1669 // check for option FilterByTime
1670 if (m_filterByPulseTime) {
1671 size_t num_proton_charges = m_eventWS->run().getProperty("proton_charge")->size();
1672 if (num_proton_charges < m_vecSplitterTime.size()) {
1673 // throw an exception if there more splitters than proton charges
1674 std::stringstream errmsg;
1675 errmsg << "It is not proper to split fast event 'By PulseTime'', when "
1676 "there are "
1677 "more splitters ("
1678 << m_vecSplitterTime.size()
1679 << ") than pulse time "
1680 "log entries ("
1681 << num_proton_charges << ")";
1682 throw runtime_error(errmsg.str());
1683 } else
1684 g_log.warning("User should understand the inaccurancy to filter events "
1685 "by pulse time.");
1686 }
1687
1689 for (int64_t iws = 0; iws < int64_t(numberOfSpectra); ++iws) {
1691
1692 // Filter the non-skipped spectrum
1693 if (!m_vecSkip[iws]) {
1694 // Get the output event lists (should be empty) to be a map
1695 map<int, DataObjects::EventList *> outputs;
1696 PARALLEL_CRITICAL(build_elist) {
1697 for (auto &ws : m_outputWorkspacesMap) {
1698 int index = ws.first;
1699 auto &output_el = ws.second->getSpectrum(iws);
1700 outputs.emplace(index, &output_el);
1701 }
1702 }
1703
1704 // Get a holder on input workspace's event list of this spectrum
1705 const DataObjects::EventList &input_el = m_eventWS->getSpectrum(iws);
1706
1707 bool printdetail = false;
1708 if (m_useDBSpectrum)
1709 printdetail = (iws == static_cast<int64_t>(m_dbWSIndex));
1710
1711 // Perform the filtering (using the splitting function and just one
1712 // output)
1713 std::string logmessage;
1714 if (m_tofCorrType != NoneCorrect) {
1715 logmessage = input_el.splitByFullTimeMatrixSplitter(m_vecSplitterTime, m_vecSplitterGroup, outputs, true,
1716 m_detTofFactors[iws], m_detTofOffsets[iws]);
1717 } else {
1718 logmessage =
1719 input_el.splitByFullTimeMatrixSplitter(m_vecSplitterTime, m_vecSplitterGroup, outputs, false, 1.0, 0.0);
1720 }
1721
1722 if (printdetail)
1723 g_log.notice(logmessage);
1724 }
1725
1727 } // END FOR i = 0
1729
1730 // Finish (1) adding events and splitting the sample logs in each target
1731 // workspace.
1732 progress(0.1 + progressamount, "Splitting logs");
1733
1734 g_log.notice("Splitters in format of Matrixworkspace are not recommended to "
1735 "split sample logs. ");
1736
1737 // split sample logs
1738
1739 // find the maximum index of the outputs' index
1740 std::set<int>::iterator target_iter;
1741 int max_target_index = 0;
1742 for (target_iter = m_targetWorkspaceIndexSet.begin(); target_iter != m_targetWorkspaceIndexSet.end(); ++target_iter) {
1743 if (*target_iter > max_target_index)
1744 max_target_index = *target_iter;
1745 }
1746
1747 return;
1748}
1749
1750//----------------------------------------------------------------------------------------------
1758void FilterEvents::generateSplitterTSP(std::vector<std::unique_ptr<Kernel::TimeSeriesProperty<int>>> &split_tsp_vec) {
1759 // clear vector to set up
1760 split_tsp_vec.clear();
1761
1762 // initialize m_maxTargetIndex + 1 time series properties in integer
1763 for (int itarget = 0; itarget <= m_maxTargetIndex; ++itarget) {
1764 auto split_tsp = std::make_unique<Kernel::TimeSeriesProperty<int>>("splitter");
1765 // add initial value if the first splitter time is after the run start
1766 // time
1767 split_tsp->addValue(Types::Core::DateAndTime(m_runStartTime), 0);
1768 split_tsp_vec.emplace_back(std::move(split_tsp));
1769 }
1770
1771 // start to go through m_vecSplitterTime (int64) and m_vecSplitterGroup add
1772 // each entry to corresponding splitter TSP
1773 for (size_t igrp = 0; igrp < m_vecSplitterGroup.size(); ++igrp) {
1774 // get the target workspace's index and the starting
1775 int itarget = m_vecSplitterGroup[igrp];
1776 // start time of the entry with value 1
1777 DateAndTime start_time(m_vecSplitterTime[igrp]);
1778 // identify by case
1779 if (start_time < m_runStartTime) {
1780 // too early, ignore
1781 continue;
1782 }
1783
1784 // get the current TSP
1785 Kernel::TimeSeriesProperty<int> *curr_tsp = split_tsp_vec[itarget].get();
1786
1787 if (start_time == m_runStartTime) {
1788 // just same as the run start time: there must be one and only 1 entry
1789 // with value 0
1790 if (curr_tsp->size() != 1) {
1791 std::stringstream error;
1792 error << "Splitter TSP for target workspace " << itarget << " must have 1 and only 1 entry "
1793 << "if there is a splitter right at its run start time.";
1794 throw std::runtime_error(error.str());
1795 }
1796 // the first entry should have an entry with value 0
1797 if (curr_tsp->firstValue() != 0) {
1798 std::stringstream error;
1799 error << "Splitter TSP for target workspace " << itarget << " must have 1 and only 1 entry "
1800 << "with value as 0 but not " << curr_tsp->firstValue() << " if there is a splitter "
1801 << "right at its run start time.";
1802 throw std::runtime_error(error.str());
1803 }
1804 // replace the value with '1' by clearing the original one first
1805 curr_tsp->clear();
1806 }
1807
1808 // later than the run start time, then add a new entry
1809 curr_tsp->addValue(start_time, 1);
1810
1811 // add run stop time as a new entry
1812 DateAndTime stop_time(m_vecSplitterTime[igrp + 1]);
1813 curr_tsp->addValue(stop_time, 0);
1814 }
1815
1816 return;
1817}
1818
1824 std::vector<std::unique_ptr<Kernel::TimeSeriesProperty<int>>> &split_tsp_vec) {
1825 // clear vector to set up
1826 split_tsp_vec.clear();
1827
1828 // initialize m_maxTargetIndex + 1 time series properties in integer
1829 // TODO:FIXME - shall not use m_maxTargetIndex, because it is not set for
1830 // SplittersWorkspace-type splitters
1831 g_log.debug() << "Maximum target index = " << m_maxTargetIndex << "\n";
1832 if (m_maxTargetIndex < 0)
1833 throw std::runtime_error("Maximum target index cannot be negative.");
1834
1835 // initialize the target index
1836 for (int itarget = 0; itarget <= m_maxTargetIndex; ++itarget) {
1837 auto split_tsp = std::make_unique<Kernel::TimeSeriesProperty<int>>("splitter");
1838 split_tsp->addValue(m_runStartTime, 0);
1839 split_tsp_vec.emplace_back(std::move(split_tsp));
1840 }
1841
1842 for (SplittingInterval splitter : m_splitters) {
1843 int itarget = splitter.index();
1844 if (itarget >= static_cast<int>(split_tsp_vec.size()))
1845 throw std::runtime_error("Target workspace index is out of range!");
1846
1847 if (splitter.start() == m_runStartTime) {
1848 // there should be only 1 value in the splitter and clear it.
1849 if (split_tsp_vec[itarget]->size() != 1) {
1850 throw std::runtime_error("Splitter must have 1 value with initialization.");
1851 }
1852 split_tsp_vec[itarget]->clear();
1853 }
1854 split_tsp_vec[itarget]->addValue(splitter.start(), 1);
1855 split_tsp_vec[itarget]->addValue(splitter.stop(), 0);
1856 }
1857
1858 return;
1859}
1860
1866 std::vector<std::unique_ptr<Kernel::TimeSeriesProperty<int>>> &split_tsp_vec) {
1867 g_log.debug() << "There are " << split_tsp_vec.size() << " TimeSeriesPropeties.\n"
1868 << "There are " << m_outputWorkspacesMap.size() << " Output worskpaces.\n";
1869
1870 if (split_tsp_vec.size() != m_outputWorkspacesMap.size() - 1) {
1871 g_log.warning() << "Number of Splitter vector (" << split_tsp_vec.size()
1872 << ") does not match number of filtered output workspaces (" << m_outputWorkspacesMap.size() - 1
1873 << ")\n";
1874 }
1875
1876 for (int itarget = 0; itarget < static_cast<int>(split_tsp_vec.size()); ++itarget) {
1877 // use itarget to find the workspace that is mapped
1878 std::map<int, DataObjects::EventWorkspace_sptr>::iterator ws_iter;
1879 ws_iter = m_outputWorkspacesMap.find(itarget);
1880
1881 // skip if an itarget does not have matched workspace
1882 if (ws_iter == m_outputWorkspacesMap.end()) {
1883 g_log.warning() << "iTarget " << itarget << " does not have any workspace associated.\n";
1884 continue;
1885 }
1886
1887 // get the workspace
1888 DataObjects::EventWorkspace_sptr outws = ws_iter->second;
1889
1890 // calculate the duration
1891 double duration = calculate_duration(split_tsp_vec[itarget]);
1892
1893 // add property
1894 PropertyWithValue<double> *duration_property = new PropertyWithValue<double>("duration", duration);
1895 outws->mutableRun().addProperty(duration_property, true);
1896 // note: split_tps_vec[i], the shared pointer, will be destroyed by
1897 // std::move()
1898 outws->mutableRun().addProperty(std::move(split_tsp_vec[itarget]), true);
1899 }
1900
1901 return;
1902}
1903
1911 // Get the times and values
1912 std::vector<int> split_values = splitter_tsp->valuesAsVector();
1913 std::vector<DateAndTime> split_time = splitter_tsp->timesAsVector();
1914
1915 double duration = 0.;
1916 for (size_t i = 0; i < split_values.size() - 1; ++i) {
1917 // for splitter's value == 1 (from this till 0 will be counted in the
1918 // duration)
1919 if (split_values[i] == 1) {
1920 // difference in nanosecond and then converted to second
1921 double sub_duration =
1922 1.E-9 * static_cast<double>(split_time[i + 1].totalNanoseconds() - split_time[i].totalNanoseconds());
1923 // increment
1924 duration += sub_duration;
1925 }
1926 }
1927
1928 return duration;
1929}
1930
1934std::vector<std::string> FilterEvents::getTimeSeriesLogNames() {
1935 std::vector<std::string> lognames;
1936
1937 const std::vector<Kernel::Property *> allprop = m_eventWS->mutableRun().getProperties();
1938 for (auto ip : allprop) {
1939 // cast to double log and integer log
1940 auto *dbltimeprop = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(ip);
1941 auto *inttimeprop = dynamic_cast<Kernel::TimeSeriesProperty<int> *>(ip);
1942 auto *booltimeprop = dynamic_cast<Kernel::TimeSeriesProperty<bool> *>(ip);
1943
1944 // append to vector if it is either double TimeSeries or int TimeSeries
1945 if (dbltimeprop || inttimeprop || booltimeprop) {
1946 const std::string &pname = ip->name();
1947 lognames.emplace_back(pname);
1948 }
1949 }
1950
1951 return lognames;
1952}
1953
1954} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const uint32_t UNDEFINED_SPLITTING_TARGET(0)
(integer) splitting target for undefined region, which will be recorded in m_splitterGroup
const int64_t TOLERANCE(1000000)
double error
Definition: IndexPeaks.cpp:133
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
double left
Definition: LineProfile.cpp:80
double right
Definition: LineProfile.cpp:81
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
Definition: MultiThreaded.h:94
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_CRITICAL(name)
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
Definition: Algorithm.cpp:2008
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
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
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
void splitByTime(std::vector< Kernel::SplittingInterval > &, std::vector< Kernel::PropertyManager * >) const override
Definition: Algorithm.h:368
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
void addTimer(const std::string &name, const Kernel::time_point_ns &begin, const Kernel::time_point_ns &end)
The Analysis data service stores instances of the Workspace objects and anything that derives from te...
const std::set< detid_t > & getDetectorIDs() const
Get a const reference to the detector IDs set.
Definition: ISpectrum.cpp:113
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
std::string & String(size_t col)
Returns a reference to the element in position col if its type is std::string.
Definition: TableRow.h:150
int & Int(size_t col)
Returns a reference to the element in position col if its type is int.
Definition: TableRow.h:131
A property class for workspaces.
FilterEvents : Filter Events in EventWorkspace to multiple EventsWorkspace by Splitters.
Definition: FilterEvents.h:29
std::vector< std::string > m_wsNames
Definition: FilterEvents.h:158
void processAlgorithmProperties()
Process user input properties.
DataObjects::SplittersWorkspace_sptr m_splittersWorkspace
Definition: FilterEvents.h:145
std::vector< std::string > getTimeSeriesLogNames()
get the names of all the time series properties in the input workspace's Run object
std::vector< double > m_detTofOffsets
Definition: FilterEvents.h:160
void generateSplitterTSPalpha(std::vector< std::unique_ptr< Kernel::TimeSeriesProperty< int > > > &split_tsp_vec)
Generate the splitter's time series property (log) the splitters workspace.
Kernel::TimeSplitterType m_splitters
Definition: FilterEvents.h:156
void processSplittersWorkspace()
process splitters given by a SplittersWorkspace
void mapSplitterTSPtoWorkspaces(std::vector< std::unique_ptr< Kernel::TimeSeriesProperty< int > > > &split_tsp_vec)
Add time series property 'Splitter' to each child workspace.
std::vector< bool > m_vecSkip
Vector for skip information.
Definition: FilterEvents.h:204
void createOutputWorkspacesSplitters()
create output workspaces if the splitters are given in SplittersWorkspace
std::map< int, std::string > m_wsGroupIndexTargetMap
Definition: FilterEvents.h:176
void splitTimeSeriesProperty(Kernel::TimeSeriesProperty< TYPE > *tsp, std::vector< Types::Core::DateAndTime > &split_datetime_vec, const int max_target_index)
split one single time-series property (template)
std::vector< double > m_detTofFactors
Definition: FilterEvents.h:161
Types::Core::DateAndTime m_filterStartTime
Definition: FilterEvents.h:209
TimeAtSampleStrategy * setupIndirectTOFCorrection() const
Set up detector calibration parameters for indirect inelastic scattering instrument.
bool m_toGroupWS
Flag to group workspace.
Definition: FilterEvents.h:183
void filterEventsBySplitters(double progressamount)
Filter events by splitters in format of Splitter.
std::set< int > m_targetWorkspaceIndexSet
Definition: FilterEvents.h:154
std::map< int, DataObjects::EventWorkspace_sptr > m_outputWorkspacesMap
Definition: FilterEvents.h:157
void examineAndSortEventWS()
Examine workspace.
std::map< std::string, int > m_targetIndexMap
TableWorkspace splitters: from target map to vector workspace group-index These 2 maps are compliment...
Definition: FilterEvents.h:175
std::map< int, uint32_t > m_yIndexMap
MatrixWorkspace splitters:
Definition: FilterEvents.h:179
void copyNoneSplitLogs(std::vector< Kernel::TimeSeriesProperty< int > * > &int_tsp_name_vector, std::vector< Kernel::TimeSeriesProperty< double > * > &dbl_tsp_name_vector, std::vector< Kernel::TimeSeriesProperty< bool > * > &bool_tsp_name_vector, std::vector< Kernel::TimeSeriesProperty< std::string > * > &string_tsp_vector)
Clone the sample logs that will not be split, including single-value and add all the TimeSeriesProper...
void generateSplitterTSP(std::vector< std::unique_ptr< Kernel::TimeSeriesProperty< int > > > &split_tsp_vec)
Generate a vector of integer time series property for each splitter corresponding to each target (in ...
void exec() override
Execution body.
std::vector< int > m_vecSplitterGroup
Vector for splitting group.
Definition: FilterEvents.h:189
void splitTimeSeriesLogs(const std::vector< Kernel::TimeSeriesProperty< int > * > &int_tsp_vector, const std::vector< Kernel::TimeSeriesProperty< double > * > &dbl_tsp_vector, const std::vector< Kernel::TimeSeriesProperty< bool > * > &bool_tsp_vector, const std::vector< Kernel::TimeSeriesProperty< std::string > * > &string_tsp_vector)
Split ALL the TimeSeriesProperty sample logs to all the output workspace.
void groupOutputWorkspace()
group output workspaces
void setupDetectorTOFCalibration()
Set up detector calibration parameters.
void setupCustomizedTOFCorrection()
Set up detector calibration parameters from customized values.
std::string m_outputWSNameBase
Base of output workspace's name.
Definition: FilterEvents.h:171
void createOutputWorkspacesTableSplitterCase()
create output workspaces in the case of using TableWorlspace for splitters
void createOutputWorkspacesMatrixCase()
create output workspaces in the case of using MatrixWorkspace for splitters
void processMatrixSplitterWorkspace()
process splitters given by a MatrixWorkspace
void filterEventsByVectorSplitters(double progressamount)
Filter events by splitters in format of vector.
EVENTFILTERSKIP m_specSkipType
Spectrum skip type.
Definition: FilterEvents.h:202
API::MatrixWorkspace_const_sptr m_matrixSplitterWS
Definition: FilterEvents.h:147
std::vector< int64_t > m_vecSplitterTime
Vector for splitting time FIXME - shall we convert this to DateAndTime???.
Definition: FilterEvents.h:187
std::map< uint32_t, int > m_wsGroupdYMap
Definition: FilterEvents.h:180
std::map< std::string, std::string > validateInputs() override
Method checking errors on ALL the inputs, before execution.
DataObjects::TableWorkspace_sptr m_informationWS
Definition: FilterEvents.h:165
TOFCorrectionType m_tofCorrType
TOF detector/sample correction type.
Definition: FilterEvents.h:199
TimeAtSampleStrategy * setupElasticTOFCorrection() const
Set up detector calibration parameters for elastic scattering instrument.
Types::Core::DateAndTime m_runStartTime
Definition: FilterEvents.h:211
DataObjects::TableWorkspace_sptr m_detCorrectWorkspace
Definition: FilterEvents.h:148
DataObjects::EventWorkspace_sptr m_eventWS
Definition: FilterEvents.h:144
bool m_useSplittersWorkspace
Flag to use matrix splitters or table splitters.
Definition: FilterEvents.h:151
bool m_splitSampleLogs
Flag to split sample logs.
Definition: FilterEvents.h:192
DataObjects::TableWorkspace_sptr m_splitterTableWorkspace
Definition: FilterEvents.h:146
TimeAtSampleStrategy * setupDirectTOFCorrection() const
Set up detector calibration parmaeters for direct inelastic scattering instrument.
double calculate_duration(std::unique_ptr< Kernel::TimeSeriesProperty< int > > &splitter_tsp)
calculate split-workspace's duration according to splitter time series property
void convertSplittersWorkspaceToVectors()
Convert SplittersWorkspace to vector of time and vector of target (itarget)
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
Definition: FilterEvents.h:39
void init() override
Declare Inputs.
void processTableSplittersWorkspace()
process the input splitters given by a TableWorkspace The method will transfer the start/stop time to...
TimeAtSampleStrategyDirect : Determine the Time at Sample corrections for a Direct Geometry instrumen...
TimeAtSampleStrategyElastic : Time at sample stragegy for elastic scattering.
TimeAtSampleStrategyIndirect : Determine Time At Sample for an indirect instrument setup.
TimeAtSampleStrategy : Strategy (technique dependent) for determining Time At Sample.
A class for holding :
Definition: EventList.h:56
std::size_t getNumberEvents() const override
Return the number of events in the list.
Definition: EventList.cpp:1143
void splitByFullTime(Kernel::TimeSplitterType &splitter, std::map< int, EventList * > outputs, bool docorrection, double toffactor, double tofshift) const
Split the event list into n outputs by event's full time (tof + pulse time)
Definition: EventList.cpp:4070
void splitByPulseTime(Kernel::TimeSplitterType &splitter, std::map< int, EventList * > outputs) const
Split events by pulse time.
Definition: EventList.cpp:4420
std::string splitByFullTimeMatrixSplitter(const std::vector< int64_t > &vec_splitters_time, const std::vector< int > &vecgroups, std::map< int, EventList * > vec_outputEventList, bool docorrection, double toffactor, double tofshift) const
Split ...
Definition: EventList.cpp:4290
Class to represent a particular goniometer setting, which is described by the rotation matrix.
Definition: Goniometer.h:55
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
std::shared_ptr< T > retrieve(const std::string &name) const
Get a shared pointer to a stored data object.
Definition: DataService.h:350
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
The concrete, templated class for properties.
virtual const std::string & units() const
Returns the units of the property, if any, as a string.
Definition: Property.cpp:179
const std::string & name() const
Get the property's name.
Definition: Property.cpp:60
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class holding a start/end time and a destination for splitting event lists and logs.
Definition: TimeSplitter.h:23
Types::Core::DateAndTime stop() const
Return the stop time.
int index() const
Return the index (destination of this split time block)
Types::Core::DateAndTime start() const
Return the start time.
A specialised Property class for holding a series of time-value pairs.
int size() const override
Returns the number of values at UNIQUE time intervals in the time series.
Types::Core::DateAndTime firstTime() const
Returns the first time regardless of filter.
TYPE firstValue() const
Returns the first value regardless of filter.
void addValue(const Types::Core::DateAndTime &time, const TYPE &value)
Add a value to the map using a DateAndTime object.
void clear() override
Deletes the series of values in the property.
void splitByTimeVector(const std::vector< Types::Core::DateAndTime > &splitter_time_vec, const std::vector< int > &target_vec, const std::vector< TimeSeriesProperty * > &outputs)
New split method.
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< const Workspace > Workspace_const_sptr
shared pointer to Mantid::API::Workspace (const version)
Definition: Workspace_fwd.h:22
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< const TableWorkspace > TableWorkspace_const_sptr
shared pointer to Mantid::DataObjects::TableWorkspace (const version)
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
MANTID_KERNEL_DLL std::string removeSpace(const std::string &CLine)
strip all spaces
Definition: Strings.cpp:300
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition: Strings.cpp:665
Helper class which provides the Collimation Length for SANS instruments.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
STL namespace.
The Correction struct to be applied as factor * TOF + offset offset:: TOF offset in unit of TOF facto...
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54