From f830ed0150df11c141653f30a1a2413dac088282 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 5 Jun 2017 07:46:17 -0400 Subject: [PATCH 01/18] Refs #19406. Made changes and based upon release 3.10 modified: Algorithms/inc/MantidAlgorithms/FilterEvents.h modified: Algorithms/src/FilterEvents.cpp modified: Algorithms/test/FilterEventsTest.h modified: Kernel/src/TimeSeriesProperty.cpp --- .../inc/MantidAlgorithms/FilterEvents.h | 66 +- Framework/Algorithms/src/FilterEvents.cpp | 592 +++++++++++++----- Framework/Algorithms/test/FilterEventsTest.h | 12 +- Framework/Kernel/src/TimeSeriesProperty.cpp | 31 +- 4 files changed, 515 insertions(+), 186 deletions(-) diff --git a/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h b/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h index 076a14b38039..83455957d738 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h @@ -74,6 +74,8 @@ class DLLExport FilterEvents : public API::Algorithm { } private: + friend struct Mantid::Kernel::CreateUsingNew; + // Implement abstract Algorithm methods void init() override; // Implement abstract Algorithm methods @@ -90,6 +92,9 @@ class DLLExport FilterEvents : public API::Algorithm { /// process splitters given by a MatrixWorkspace void processMatrixSplitterWorkspace(); + /// create event workspace + boost::shared_ptr createEventWorkspaceNoLog(); + /// create output workspaces if the splitters are given in SplittersWorkspace void createOutputWorkspaces(); /// create output workspaces in the case of using TableWorlspace for splitters void createOutputWorkspacesTableSplitterCase(); @@ -127,6 +132,49 @@ class DLLExport FilterEvents : public API::Algorithm { /// (itarget) void convertSplittersWorkspaceToVectors(); + void splitTimeSeriesLogs( + const std::vector *> &int_tsp_vector, + const std::vector *> &dbl_tsp_vector, + const std::vector *> &bool_tsp_vector); + + /// get the names of all the time series properties in the input workspace's + /// Run object + std::vector getTimeSeriesLogNames(); + + // Kernel::TimeSplitterType generateSplitters(int wsindex); + + void generateSplitterTSP( + std::vector *> &split_tsp_vec); + + void generateSplitterTSPalpha( + std::vector *> &split_tsp_vec); + + /// + void mapSplitterTSPtoWorkspaces( + const std::vector *> &split_tsp_vec); + + // void splitTSPLogInPlace(DataObjects::EventWorkspace_sptr eventws, + // std::string logname, + // Kernel::TimeSplitterType &splitters); + + void copyNoneSplitLogs( + std::vector *> &int_tsp_name_vector, + std::vector *> &dbl_tsp_name_vector, + std::vector *> &bool_tsp_name_vector); + + template + void + splitTimeSeriesProperty(Kernel::TimeSeriesProperty *tsp, + std::vector &split_datetime_vec, + const int max_target_index); + + void splitDoubleTimeSeriesLogs( + const std::vector *> &dbl_tsp_vector, + std::vector &split_datetime_vec, + const int max_target_index); + + void groupOutputWorkspace(); + DataObjects::EventWorkspace_sptr m_eventWS; DataObjects::SplittersWorkspace_sptr m_splittersWorkspace; DataObjects::TableWorkspace_sptr m_splitterTableWorkspace; @@ -153,24 +201,6 @@ class DLLExport FilterEvents : public API::Algorithm { double m_progress; - /// DOC! TODO - std::vector getTimeSeriesLogNames(); - - Kernel::TimeSplitterType generateSplitters(int wsindex); - - void generateSplitterTSP( - std::vector *> &split_tsp_vec); - - void generateSplitterTSPalpha( - std::vector *> &split_tsp_vec); - - /// - void mapSplitterTSPtoWorkspaces( - const std::vector *> &split_tsp_vec); - - void splitLog(DataObjects::EventWorkspace_sptr eventws, std::string logname, - Kernel::TimeSplitterType &splitters); - /// Base of output workspace's name std::string m_outputWSNameBase; diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index d280eff7b465..c6a6a303d562 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -20,6 +20,9 @@ #include "MantidKernel/System.h" #include "MantidKernel/TimeSeriesProperty.h" #include "MantidKernel/VisibleWhenProperty.h" +#include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/Strings.h" + #include #include @@ -152,6 +155,20 @@ void FilterEvents::init() { declareProperty( "FilterStartTime", "", "Start time for splitters that can be parsed to DateAndTime."); + + declareProperty( + Kernel::make_unique>("TimeSeriesPropertyLogs"), + "List of name of sample logs of TimeSeriesProperty format. " + "They will be either excluded from splitting if ExcludedSpecifiedLogs is " + "specified as True. Or " + "They will be the only TimeSeriesProperty sample logs that will be split " + "to child workspaces."); + + declareProperty("ExcludeSpecifiedLogs", true, + "If true, all the TimeSeriesProperty logs listed will be " + "excluded from duplicating. " + "Otherwise, only those specified logs will be split."); + } /** Execution body @@ -183,6 +200,12 @@ void FilterEvents::exec() { else createOutputWorkspacesMatrixCase(); + // clone the properties but TimeSeriesProperty + std::vector *> int_tsp_vector; + std::vector *> dbl_tsp_vector; + std::vector *> bool_tsp_vector; + copyNoneSplitLogs(int_tsp_vector, dbl_tsp_vector, bool_tsp_vector); + // Optionall import corrections m_progress = 0.20; progress(m_progress, "Importing TOF corrections. "); @@ -209,6 +232,25 @@ void FilterEvents::exec() { // assign split_tsp_vector to all the output workspaces! mapSplitterTSPtoWorkspaces(split_tsp_vector); + // split times series property: new way to split events + splitTimeSeriesLogs(int_tsp_vector, dbl_tsp_vector, bool_tsp_vector); + + // Optional to group detector + groupOutputWorkspace(); + + // Form the names of output workspaces + std::vector outputwsnames; + std::map::iterator miter; + for (miter = m_outputWorkspacesMap.begin(); + miter != m_outputWorkspacesMap.end(); ++miter) { + outputwsnames.push_back(miter->second->getName()); + } + setProperty("OutputWorkspaceNames", outputwsnames); + + m_progress = 1.0; + progress(m_progress, "Completed"); + + /* // Optional to group detector // TODO:FIXME - move this part to a method if (m_toGroupWS) { @@ -243,6 +285,73 @@ void FilterEvents::exec() { m_progress = 1.0; progress(m_progress, "Completed"); + */ +} + +//---------------------------------------------------------------------------------------------- +/** Examine whether any spectrum does not have detector + * Warning message will be written out + * @brief FilterEvents::examineEventWS + */ +void FilterEvents::examineAndSortEventWS() { + // get event workspace information + size_t numhist = m_eventWS->getNumberHistograms(); + m_vecSkip.resize(numhist, false); + + // check whether any detector is skipped + if (m_specSkipType == EventFilterSkipNoDetTOFCorr && + m_tofCorrType == NoneCorrect) { + // No TOF correction and skip spectrum only if TOF correction is required + g_log.warning( + "By user's choice, No spectrum will be skipped even if it has " + "no detector."); + } else { + // check detectors whether there is any of them that will be skipped + stringstream msgss; + size_t numskipspec = 0; + size_t numeventsskip = 0; + + const auto &spectrumInfo = m_eventWS->spectrumInfo(); + for (size_t i = 0; i < numhist; ++i) { + if (!spectrumInfo.hasDetectors(i)) { + m_vecSkip[i] = true; + + ++numskipspec; + const EventList &elist = m_eventWS->getSpectrum(i); + numeventsskip += elist.getNumberEvents(); + msgss << i; + if (numskipspec % 10 == 0) + msgss << "\n"; + else + msgss << ","; + } + } // ENDFOR + + if (numskipspec > 0) { + g_log.warning() + << "There are " << numskipspec + << " spectra that do not have detectors. " + << "They will be skipped during filtering. There are total " + << numeventsskip + << " events in those spectra. \nList of these specta is as below:\n" + << msgss.str() << "\n"; + } else { + g_log.notice("There is no spectrum that does not have detectors."); + } + + } // END-IF-ELSE + + // sort events + DataObjects::EventSortType sortType = DataObjects::TOF_SORT; + if (m_filterByPulseTime) + sortType = DataObjects::PULSETIME_SORT; + else + sortType = DataObjects::PULSETIMETOF_SORT; + + // This runs the SortEvents algorithm in parallel + m_eventWS->sortAll(sortType, nullptr); + + return; } //---------------------------------------------------------------------------------------------- @@ -367,71 +476,315 @@ void FilterEvents::processAlgorithmProperties() { } //---------------------------------------------------------------------------------------------- -/** Examine whether any spectrum does not have detector - * Warning message will be written out - * @brief FilterEvents::examineEventWS +/** group output workspaces + * @brief FilterEvents::groupOutputWorkspace */ -void FilterEvents::examineAndSortEventWS() { - // get event workspace information - size_t numhist = m_eventWS->getNumberHistograms(); - m_vecSkip.resize(numhist, false); +void FilterEvents::groupOutputWorkspace() { + // TODO:FIXME - move this part to a method + if (m_toGroupWS) { + m_progress = 0.9; + progress(m_progress, "Group workspaces"); - // check whether any detector is skipped - if (m_specSkipType == EventFilterSkipNoDetTOFCorr && - m_tofCorrType == NoneCorrect) { - // No TOF correction and skip spectrum only if TOF correction is required - g_log.warning( - "By user's choice, No spectrum will be skipped even if it has " - "no detector."); - } else { - // check detectors whether there is any of them that will be skipped - stringstream msgss; - size_t numskipspec = 0; - size_t numeventsskip = 0; + std::string groupname = m_outputWSNameBase; + API::IAlgorithm_sptr groupws = + createChildAlgorithm("GroupWorkspaces", 0.99, 1.00, true); + // groupws->initialize(); + groupws->setAlwaysStoreInADS(true); + groupws->setProperty("InputWorkspaces", m_wsNames); + groupws->setProperty("OutputWorkspace", groupname); + groupws->execute(); + if (!groupws->isExecuted()) { + g_log.error() << "Grouping all output workspaces fails.\n"; + } + } +} - const auto &spectrumInfo = m_eventWS->spectrumInfo(); - for (size_t i = 0; i < numhist; ++i) { - if (!spectrumInfo.hasDetectors(i)) { - m_vecSkip[i] = true; +//---------------------------------------------------------------------------------------------- +/** Clone the sample logs that will not be split and add all the + * TimeSeriesProperty sample logs + * to vectors by their type + * @brief FilterEvents::copyNoneSplitLogs + * @param int_tsp_name_vector :: output + * @param dbl_tsp_name_vector :: output + * @param bool_tsp_name_vector :: output + */ +void FilterEvents::copyNoneSplitLogs( + std::vector *> &int_tsp_name_vector, + std::vector *> &dbl_tsp_name_vector, + std::vector *> &bool_tsp_name_vector) { + // get the user input information + bool exclude_listed_logs = getProperty("ExcludeSpecifiedLogs"); + std::vector tsp_logs = getProperty("TimeSeriesPropertyLogs"); + // convert to set + std::set tsp_logs_set; + for (auto iter = tsp_logs.begin(); iter != tsp_logs.end(); ++iter) + tsp_logs_set.insert(*iter); + + std::set::iterator set_iter; + // initialize + int_tsp_name_vector.clear(); + dbl_tsp_name_vector.clear(); + bool_tsp_name_vector.clear(); + + std::vector prop_vector = m_eventWS->run().getProperties(); + for (size_t i = 0; i < prop_vector.size(); ++i) { + // get property + Property *prop_i = prop_vector[i]; + std::string name_i = prop_i->name(); + + // cast to different type of TimeSeriesProperties + TimeSeriesProperty *dbl_prop = + dynamic_cast *>(prop_i); + TimeSeriesProperty *int_prop = + dynamic_cast *>(prop_i); + TimeSeriesProperty *bool_prop = + dynamic_cast *>(prop_i); + + // check for time series properties + if (dbl_prop || int_prop || bool_prop) { + // check whether the log is there + set_iter = tsp_logs_set.find(name_i); + if (exclude_listed_logs && set_iter != tsp_logs_set.end()) { + // exclude all the listed tsp logs and this log name is in the set + // skip + g_log.information() << "Skip splitting sample log " << name_i << "\n"; + continue; + } else if (!exclude_listed_logs && set_iter == tsp_logs_set.end()) { + // include all the listed tsp logs to split but this log name is NOT in + // the set + // skip + g_log.information() << "Skip splitting sample log " << name_i << "\n"; + continue; + } - ++numskipspec; - const EventList &elist = m_eventWS->getSpectrum(i); - numeventsskip += elist.getNumberEvents(); - msgss << i; - if (numskipspec % 10 == 0) - msgss << "\n"; + // insert the time series property to proper target vector + if (dbl_prop) { + // is double time series property + dbl_tsp_name_vector.push_back(dbl_prop); + } else if (int_prop) { + // is integer time series property + int_tsp_name_vector.push_back(int_prop); + } else if (bool_prop) { + // is integer time series property + bool_tsp_name_vector.push_back(bool_prop); + continue; + } + + } else { + // non time series properties + // single value property: copy to the new workspace + std::map::iterator ws_iter; + for (ws_iter = m_outputWorkspacesMap.begin(); + ws_iter != m_outputWorkspacesMap.end(); ++ws_iter) { + + std::string value_i = prop_i->value(); + double double_v; + int int_v; + if (Strings::convert(value_i, double_v) != 0) // double value + ws_iter->second->mutableRun().addProperty(name_i, double_v, true); + else if (Strings::convert(value_i, int_v) != 0) + ws_iter->second->mutableRun().addProperty(name_i, int_v, true); else - msgss << ","; + ws_iter->second->mutableRun().addProperty(name_i, value_i, true); } - } // ENDFOR + } + } // end for - if (numskipspec > 0) { - g_log.warning() - << "There are " << numskipspec - << " spectra that do not have detectors. " - << "They will be skipped during filtering. There are total " - << numeventsskip - << " events in those spectra. \nList of these specta is as below:\n" - << msgss.str() << "\n"; + return; +} + +//---------------------------------------------------------------------------------------------- +/** Split all the TimeSeriesProperty sample logs to all the output workspace + * @brief FilterEvents::splitTimeSeriesLogs + * @param int_tsp_vector + * @param dbl_tsp_vector + * @param bool_tsp_vector + */ +void FilterEvents::splitTimeSeriesLogs( + const std::vector *> &int_tsp_vector, + const std::vector *> &dbl_tsp_vector, + const std::vector *> &bool_tsp_vector) { + // get split times by converting vector of int64 to Time + std::vector split_datetime_vec; + + // convert splitters workspace to vectors used by TableWorkspace and + // MatrixWorkspace splitters + if (m_useSplittersWorkspace) { + convertSplittersWorkspaceToVectors(); + } + + // convert splitter time vector to DateAndTime format + split_datetime_vec.resize(m_vecSplitterTime.size()); + for (size_t i = 0; i < m_vecSplitterTime.size(); ++i) { + DateAndTime split_time(m_vecSplitterTime[i]); + split_datetime_vec[i] = split_time; + } + + // find the maximum index of the outputs' index + std::set::iterator target_iter; + int max_target_index = 0; + for (target_iter = m_targetWorkspaceIndexSet.begin(); + target_iter != m_targetWorkspaceIndexSet.end(); ++target_iter) { + if (*target_iter > max_target_index) + max_target_index = *target_iter; + } + g_log.information() << "Maximum target index = " << max_target_index << "\n"; + + // splitters workspace need to have 1 more for left-over events + if (m_useSplittersWorkspace) + ++max_target_index; + + // deal with integer time series property + for (size_t i = 0; i < int_tsp_vector.size(); ++i) { + splitTimeSeriesProperty(int_tsp_vector[i], split_datetime_vec, + max_target_index); + } + + // split double time series property + for (size_t i = 0; i < dbl_tsp_vector.size(); ++i) { + splitTimeSeriesProperty(dbl_tsp_vector[i], split_datetime_vec, + max_target_index); + } + + // deal with bool time series property + for (size_t i_bool = 0; i_bool < bool_tsp_vector.size(); ++i_bool) { + splitTimeSeriesProperty(bool_tsp_vector[i_bool], split_datetime_vec, + max_target_index); + } + + // integrate proton charge + for (int tindex = 0; tindex <= max_target_index; ++tindex) { + // find output workspace + std::map::iterator wsiter; + wsiter = m_outputWorkspacesMap.find(tindex); + if (wsiter == m_outputWorkspacesMap.end()) { + g_log.information() << "Workspace target (indexed as " << tindex + << ") does not have workspace associated.\n"; } else { - g_log.notice("There is no spectrum that does not have detectors."); + DataObjects::EventWorkspace_sptr ws_i = wsiter->second; + ws_i->mutableRun().integrateProtonCharge(); } + } - } // END-IF-ELSE + return; +} - // sort events - DataObjects::EventSortType sortType = DataObjects::TOF_SORT; - if (m_filterByPulseTime) - sortType = DataObjects::PULSETIME_SORT; - else - sortType = DataObjects::PULSETIMETOF_SORT; +//---------------------------------------------------------------------------------------------- +template +void FilterEvents::splitTimeSeriesProperty( + Kernel::TimeSeriesProperty *tsp, + std::vector &split_datetime_vec, + const int max_target_index) { + // skip the sample logs if they are specified + // get property name and etc + std::string property_name = tsp->name(); + // generate new propertys for the source to split to + std::vector *> output_vector; + for (int tindex = 0; tindex <= max_target_index; ++tindex) { + TimeSeriesProperty *new_property = + new TimeSeriesProperty(property_name); + new_property->setUnits(tsp->units()); + output_vector.push_back(new_property); + } - // This runs the SortEvents algorithm in parallel - m_eventWS->sortAll(sortType, nullptr); + // duplicate the time series property if the size is just one + if (tsp->size() == 1) { + // duplicate + for (size_t i_out = 0; i_out < output_vector.size(); ++i_out) { + output_vector[i_out]->addValue(tsp->firstTime(), tsp->firstValue()); + } + } else { + // split log + tsp->splitByTimeVector(split_datetime_vec, m_vecSplitterGroup, + output_vector); + } + + // assign to output workspaces + for (int tindex = 0; tindex <= max_target_index; ++tindex) { + // find output workspace + std::map::iterator wsiter; + wsiter = m_outputWorkspacesMap.find(tindex); + if (wsiter == m_outputWorkspacesMap.end()) { + // unable to find workspace associated with target index + g_log.information() << "Workspace target (" << tindex + << ") does not have workspace associated." + << "\n"; + } else { + // add property to the associated workspace + DataObjects::EventWorkspace_sptr ws_i = wsiter->second; + ws_i->mutableRun().addProperty(output_vector[tindex], true); + } + } return; } +//---------------------------------------------------------------------------------------------- +//** Examine whether any spectrum does not have detector +// * Warning message will be written out +// * @brief FilterEvents::examineEventWS +// */ +//void FilterEvents::examineAndSortEventWS() { +// // get event workspace information +// size_t numhist = m_eventWS->getNumberHistograms(); +// m_vecSkip.resize(numhist, false); + +// // check whether any detector is skipped +// if (m_specSkipType == EventFilterSkipNoDetTOFCorr && +// m_tofCorrType == NoneCorrect) { +// // No TOF correction and skip spectrum only if TOF correction is required +// g_log.warning( +// "By user's choice, No spectrum will be skipped even if it has " +// "no detector."); +// } else { +// // check detectors whether there is any of them that will be skipped +// stringstream msgss; +// size_t numskipspec = 0; +// size_t numeventsskip = 0; + +// const auto &spectrumInfo = m_eventWS->spectrumInfo(); +// for (size_t i = 0; i < numhist; ++i) { +// if (!spectrumInfo.hasDetectors(i)) { +// m_vecSkip[i] = true; + +// ++numskipspec; +// const EventList &elist = m_eventWS->getSpectrum(i); +// numeventsskip += elist.getNumberEvents(); +// msgss << i; +// if (numskipspec % 10 == 0) +// msgss << "\n"; +// else +// msgss << ","; +// } +// } // ENDFOR + +// if (numskipspec > 0) { +// g_log.warning() +// << "There are " << numskipspec +// << " spectra that do not have detectors. " +// << "They will be skipped during filtering. There are total " +// << numeventsskip +// << " events in those spectra. \nList of these specta is as below:\n" +// << msgss.str() << "\n"; +// } else { +// g_log.notice("There is no spectrum that does not have detectors."); +// } + +// } // END-IF-ELSE + +// // sort events +// DataObjects::EventSortType sortType = DataObjects::TOF_SORT; +// if (m_filterByPulseTime) +// sortType = DataObjects::PULSETIME_SORT; +// else +// sortType = DataObjects::PULSETIMETOF_SORT; + +// // This runs the SortEvents algorithm in parallel +// m_eventWS->sortAll(sortType, nullptr); + +// return; +//} + //---------------------------------------------------------------------------------------------- /** Purpose: * Convert SplitterWorkspace object to TimeSplitterType (sorted vector) @@ -1309,53 +1662,6 @@ void FilterEvents::filterEventsBySplitters(double progressamount) { // Split the sample logs in each target workspace. progress(0.1 + progressamount, "Splitting logs"); - - if (!m_splitSampleLogs) { - // Skip if choice is no - g_log.notice("Sample logs are not split by user's choice."); - return; - } - - auto lognames = this->getTimeSeriesLogNames(); - g_log.debug() << "[FilterEvents D1214]: Number of TimeSeries Logs = " - << lognames.size() << " to " << m_outputWorkspacesMap.size() - << " outptu workspaces. \n"; - - double numws = static_cast(m_outputWorkspacesMap.size()); - double outwsindex = 0.; - - // split sample logs from original workspace to new one - for (auto &ws : m_outputWorkspacesMap) { - int wsindex = ws.first; - DataObjects::EventWorkspace_sptr opws = ws.second; - - // Generate a list of splitters for current output workspace - Kernel::TimeSplitterType splitters = generateSplitters(wsindex); - - g_log.debug() << "[FilterEvents D1215]: Output workspace Index " << wsindex - << ": Name = " << opws->getName() - << "; Number of splitters = " << splitters.size() << ".\n"; - - // Skip output workspace has ZERO splitters - if (splitters.empty()) { - g_log.warning() << "[FilterEvents] Workspace " << opws->getName() - << " Indexed @ " << wsindex - << " won't have logs splitted due to zero splitter size. " - << ".\n"; - continue; - } - - // Split log - // FIXME-TODO: SHALL WE MOVE THIS PART OUTSIDE OF THIS METHOD? - size_t numlogs = lognames.size(); - for (size_t ilog = 0; ilog < numlogs; ++ilog) { - this->splitLog(opws, lognames[ilog], splitters); - } - opws->mutableRun().integrateProtonCharge(); - - progress(0.1 + progressamount + outwsindex / numws * 0.2, "Splitting logs"); - outwsindex += 1.; - } } /** Split events by splitters represented by vector @@ -1545,53 +1851,53 @@ void FilterEvents::filterEventsByVectorSplitters(double progressamount) { return; } -/** Generate splitters for specified workspace index as a subset of - * m_splitters - */ -Kernel::TimeSplitterType FilterEvents::generateSplitters(int wsindex) { - Kernel::TimeSplitterType splitters; - for (const auto &splitter : m_splitters) { - int index = splitter.index(); - if (index == wsindex) { - splitters.push_back(splitter); - } - } - return splitters; -} - -/** Split a log by splitters - */ -void FilterEvents::splitLog(EventWorkspace_sptr eventws, std::string logname, - TimeSplitterType &splitters) { - // cast property to both double TimeSeriesProperty and IntSeriesProperty - Kernel::TimeSeriesProperty *dbl_prop = - dynamic_cast *>( - eventws->mutableRun().getProperty(logname)); - Kernel::TimeSeriesProperty *int_prop = - dynamic_cast *>( - eventws->mutableRun().getProperty(logname)); - - if (!dbl_prop && !int_prop) { - std::stringstream errmsg; - errmsg << "Log " << logname - << " is not TimeSeriesProperty or TimeSeriesProperty. " - << "Unable to split."; - throw std::runtime_error(errmsg.str()); - } else { - for (const auto &split : splitters) { - g_log.debug() << "Workspace " << eventws->getName() << ": " - << "log name = " << logname - << ", duration = " << split.duration() << " from " - << split.start() << " to " << split.stop() << ".\n"; - } - - // split log - if (dbl_prop) - dbl_prop->filterByTimes(splitters); - else - int_prop->filterByTimes(splitters); - } -} +///** Generate splitters for specified workspace index as a subset of +// * m_splitters +// */ +//Kernel::TimeSplitterType FilterEvents::generateSplitters(int wsindex) { +// Kernel::TimeSplitterType splitters; +// for (const auto &splitter : m_splitters) { +// int index = splitter.index(); +// if (index == wsindex) { +// splitters.push_back(splitter); +// } +// } +// return splitters; +//} + +///** Split a log by splitters +// */ +//void FilterEvents::splitLog(EventWorkspace_sptr eventws, std::string logname, +// TimeSplitterType &splitters) { +// // cast property to both double TimeSeriesProperty and IntSeriesProperty +// Kernel::TimeSeriesProperty *dbl_prop = +// dynamic_cast *>( +// eventws->mutableRun().getProperty(logname)); +// Kernel::TimeSeriesProperty *int_prop = +// dynamic_cast *>( +// eventws->mutableRun().getProperty(logname)); + +// if (!dbl_prop && !int_prop) { +// std::stringstream errmsg; +// errmsg << "Log " << logname +// << " is not TimeSeriesProperty or TimeSeriesProperty. " +// << "Unable to split."; +// throw std::runtime_error(errmsg.str()); +// } else { +// for (const auto &split : splitters) { +// g_log.debug() << "Workspace " << eventws->getName() << ": " +// << "log name = " << logname +// << ", duration = " << split.duration() << " from " +// << split.start() << " to " << split.stop() << ".\n"; +// } + +// // split log +// if (dbl_prop) +// dbl_prop->filterByTimes(splitters); +// else +// int_prop->filterByTimes(splitters); +// } +//} //---------------------------------------------------------------------------------------------- /** Generate a vector of integer time series property for each splitter diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index 8f70a4a8d0df..839d0396831c 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -140,7 +140,7 @@ class FilterEventsTest : public CxxTest::TestSuite { TS_ASSERT(filteredws0); TS_ASSERT_EQUALS(filteredws0->getNumberHistograms(), 10); TS_ASSERT_EQUALS(filteredws0->getSpectrum(0).getNumberEvents(), 4); - TS_ASSERT_EQUALS(filteredws0->run().getProtonCharge(), 10); + TS_ASSERT_EQUALS(filteredws0->run().getProtonCharge(), 2); // check splitter log TS_ASSERT(filteredws0->run().hasProperty("splitter")); @@ -160,7 +160,7 @@ class FilterEventsTest : public CxxTest::TestSuite { AnalysisDataService::Instance().retrieve("FilteredWS01_1")); TS_ASSERT(filteredws1); TS_ASSERT_EQUALS(filteredws1->getSpectrum(1).getNumberEvents(), 16); - TS_ASSERT_EQUALS(filteredws1->run().getProtonCharge(), 11); + TS_ASSERT_EQUALS(filteredws1->run().getProtonCharge(), 3); // check splitter log TS_ASSERT(filteredws0->run().hasProperty("splitter")); @@ -182,7 +182,7 @@ class FilterEventsTest : public CxxTest::TestSuite { AnalysisDataService::Instance().retrieve("FilteredWS01_2")); TS_ASSERT(filteredws2); TS_ASSERT_EQUALS(filteredws2->getSpectrum(1).getNumberEvents(), 21); - TS_ASSERT_EQUALS(filteredws2->run().getProtonCharge(), 21); + TS_ASSERT_EQUALS(filteredws2->run().getProtonCharge(), 3); EventList elist3 = filteredws2->getSpectrum(3); elist3.sortPulseTimeTOF(); @@ -965,14 +965,13 @@ class FilterEventsTest : public CxxTest::TestSuite { EventWorkspace_sptr createEventWorkspace(int64_t runstart_i64, int64_t pulsedt, int64_t tofdt, size_t numpulses) { - // 1. Create an EventWorkspace with 10 detectors + // Create an EventWorkspace with 10 detectors EventWorkspace_sptr eventWS = WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(10, 1, true); Kernel::DateAndTime runstart(runstart_i64); - // 2. Set run_start time eventWS->mutableRun().addProperty("run_start", runstart.toISO8601String(), true); @@ -986,7 +985,8 @@ class FilterEventsTest : public CxxTest::TestSuite { for (int64_t pid = 0; pid < static_cast(numpulses); pid++) { int64_t pulsetime_i64 = pid * pulsedt + runstart.totalNanoseconds(); Kernel::DateAndTime pulsetime(pulsetime_i64); - pchargeLog->addValue(pulsetime, 1.); + if (i == 0) + pchargeLog->addValue(pulsetime, 1.); for (size_t e = 0; e < 10; e++) { double tof = static_cast(e * tofdt / 1000); TofEvent event(tof, pulsetime); diff --git a/Framework/Kernel/src/TimeSeriesProperty.cpp b/Framework/Kernel/src/TimeSeriesProperty.cpp index ae861726ee8d..c1f729520d19 100644 --- a/Framework/Kernel/src/TimeSeriesProperty.cpp +++ b/Framework/Kernel/src/TimeSeriesProperty.cpp @@ -530,9 +530,13 @@ void TimeSeriesProperty::splitByTimeVector( std::vector &splitter_time_vec, std::vector &target_vec, std::vector outputs) { // check inputs - if (splitter_time_vec.size() != target_vec.size() + 1) - throw std::runtime_error("Input time vector's size does not match taget " - "workspace index vector's size."); + if (splitter_time_vec.size() != target_vec.size() + 1) { + std::stringstream errss; + errss << "Input time vector's size " << splitter_time_vec.size() + << " does not match (one more larger than) taget " + "workspace index vector's size " << target_vec.size() << "\n"; + throw std::runtime_error(errss.str()); + } // return if the output vector TimeSeriesProperties is not defined if (outputs.empty()) return; @@ -596,28 +600,20 @@ void TimeSeriesProperty::splitByTimeVector( } } - g_log.debug() << "TSP entry: " << index_tsp_time - << ", Splitter index = " << index_splitter << "\n"; - // now it is the time to put TSP's entries to corresponding continue_search = !no_entry_in_range; while (continue_search) { - // get the first entry index - if (index_tsp_time > 0) - --index_tsp_time; - + // get next target int target = target_vec[index_splitter]; - g_log.debug() << "Target = " << target - << " with splitter index = " << index_splitter << "\n" - << "\t" - << "Time index = " << index_tsp_time << "\n\n"; + // get the first entry index (overlap) + if (index_tsp_time > 0) + --index_tsp_time; + // add the continous entries to same target time series property bool continue_add = true; while (continue_add) { // add current entry - g_log.debug() << "Add entry " << index_tsp_time << " to target " << target - << "\n"; if (outputs[target]->size() == 0 || outputs[target]->lastTime() < tsp_time) { // avoid to add duplicate entry @@ -628,9 +624,6 @@ void TimeSeriesProperty::splitByTimeVector( // advance to next entry ++index_tsp_time; - g_log.debug() << "\tEntry time " << tsp_time_vec[index_tsp_time] - << ", stop time " << split_stop_time << "\n"; - if (index_tsp_time == tsp_time_vec.size()) { // last entry. quit all loops continue_add = false; From 0df48cfd5a6d90786495c5dfc1a80184c178c91b Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 5 Jun 2017 11:49:30 -0400 Subject: [PATCH 02/18] Refs #19406. Fixed some minor issues. --- Framework/Algorithms/src/FilterEvents.cpp | 252 ++++------------------ 1 file changed, 41 insertions(+), 211 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index c6a6a303d562..93b40a2a6b3d 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -168,7 +168,6 @@ void FilterEvents::init() { "If true, all the TimeSeriesProperty logs listed will be " "excluded from duplicating. " "Otherwise, only those specified logs will be split."); - } /** Execution body @@ -249,43 +248,6 @@ void FilterEvents::exec() { m_progress = 1.0; progress(m_progress, "Completed"); - - /* - // Optional to group detector - // TODO:FIXME - move this part to a method - if (m_toGroupWS) { - m_progress = 0.9; - progress(m_progress, "Group workspaces"); - - std::string groupname = m_outputWSNameBase; - API::IAlgorithm_sptr groupws = - createChildAlgorithm("GroupWorkspaces", 0.99, 1.00, true); - // groupws->initialize(); - groupws->setAlwaysStoreInADS(true); - groupws->setProperty("InputWorkspaces", m_wsNames); - groupws->setProperty("OutputWorkspace", groupname); - groupws->execute(); - if (!groupws->isExecuted()) { - g_log.error() << "Grouping all output workspaces fails.\n"; - } - } - - // TODO:FIXME - move this part to a method - // Form the names of output workspaces - std::vector outputwsnames; - std::map::iterator miter; - // for (miter = m_outputWorkspacesMap.begin(); - // miter != m_outputWorkspacesMap.end(); ++miter) { - // outputwsnames.push_back(miter->second->name()); - for (miter = m_outputWorkspacesMap.begin(); - miter != m_outputWorkspacesMap.end(); ++miter) { - outputwsnames.push_back(miter->second->getName()); - } - setProperty("OutputWorkspaceNames", outputwsnames); - - m_progress = 1.0; - progress(m_progress, "Completed"); - */ } //---------------------------------------------------------------------------------------------- @@ -480,23 +442,27 @@ void FilterEvents::processAlgorithmProperties() { * @brief FilterEvents::groupOutputWorkspace */ void FilterEvents::groupOutputWorkspace() { - // TODO:FIXME - move this part to a method - if (m_toGroupWS) { - m_progress = 0.9; - progress(m_progress, "Group workspaces"); - - std::string groupname = m_outputWSNameBase; - API::IAlgorithm_sptr groupws = - createChildAlgorithm("GroupWorkspaces", 0.99, 1.00, true); - // groupws->initialize(); - groupws->setAlwaysStoreInADS(true); - groupws->setProperty("InputWorkspaces", m_wsNames); - groupws->setProperty("OutputWorkspace", groupname); - groupws->execute(); - if (!groupws->isExecuted()) { - g_log.error() << "Grouping all output workspaces fails.\n"; - } + // return if there is no such need + if (!m_toGroupWS) + return; + + // set progress + m_progress = 0.95; + progress(m_progress, "Group workspaces"); + + std::string groupname = m_outputWSNameBase; + API::IAlgorithm_sptr groupws = + createChildAlgorithm("GroupWorkspaces", 0.95, 1.00, true); + // groupws->initialize(); + groupws->setAlwaysStoreInADS(true); + groupws->setProperty("InputWorkspaces", m_wsNames); + groupws->setProperty("OutputWorkspace", groupname); + groupws->execute(); + if (!groupws->isExecuted()) { + g_log.error() << "Grouping all output workspaces fails.\n"; } + + return; } //---------------------------------------------------------------------------------------------- @@ -724,7 +690,7 @@ void FilterEvents::splitTimeSeriesProperty( // * Warning message will be written out // * @brief FilterEvents::examineEventWS // */ -//void FilterEvents::examineAndSortEventWS() { +// void FilterEvents::examineAndSortEventWS() { // // get event workspace information // size_t numhist = m_eventWS->getNumberHistograms(); // m_vecSkip.resize(numhist, false); @@ -1160,7 +1126,7 @@ void FilterEvents::createOutputWorkspaces() { } boost::shared_ptr optws = - create(*m_eventWS); + createWithoutLogs(*m_eventWS); m_outputWorkspacesMap.emplace(wsgroup, optws); // Add information, including title and comment, to output workspace @@ -1196,6 +1162,8 @@ void FilterEvents::createOutputWorkspaces() { m_wsNames.push_back(wsname.str()); // Set (property) to output workspace and set to ADS + // TODO/ISSUE/NOW - If grouping workspace later, then there is no need to + // create these output properties declareProperty( Kernel::make_unique< API::WorkspaceProperty>( @@ -1267,9 +1235,12 @@ void FilterEvents::createOutputWorkspacesMatrixCase() { // create new workspace from input EventWorkspace and all the sample logs // are copied to the new one boost::shared_ptr optws = - create(*m_eventWS); + createWithoutLogs(*m_eventWS); m_outputWorkspacesMap.emplace(wsgroup, optws); + // TODO/ISSUE/NOW - How about comment and info similar to + // createOutputWorkspaces()? + // add to output workspace property std::stringstream propertynamess; if (wsgroup == 0) { @@ -1348,9 +1319,11 @@ void FilterEvents::createOutputWorkspacesTableSplitterCase() { // create new workspace boost::shared_ptr optws = - create(*m_eventWS); + createWithoutLogs(*m_eventWS); m_outputWorkspacesMap.emplace(wsgroup, optws); + // TODO/NOW/ISSUE -- How about comment and info? + // add to output workspace property std::stringstream propertynamess; if (wsgroup < 0) { @@ -1662,6 +1635,8 @@ void FilterEvents::filterEventsBySplitters(double progressamount) { // Split the sample logs in each target workspace. progress(0.1 + progressamount, "Splitting logs"); + + return; } /** Split events by splitters represented by vector @@ -1676,23 +1651,20 @@ void FilterEvents::filterEventsByVectorSplitters(double progressamount) { "input/source EventWorkspace = " << numberOfSpectra << ".\n"; + // check for option FilterByTime if (m_filterByPulseTime) { size_t num_proton_charges = m_eventWS->run().getProperty("proton_charge")->size(); - if (num_proton_charges < m_vecSplitterTime.size()) - throw runtime_error("It is not a good practice to split fast event by " + if (num_proton_charges < m_vecSplitterTime.size()) { + // TODO/ISSUE/NOW - Better error message! + throw runtime_error("It is not a good choice to split fast event by " "pulse time when there are more splitters than pulse " "times."); - else + } else g_log.warning("User should understand the inaccurancy to filter events " "by pulse time."); } - /* - for (size_t i = 0; i < m_vecSplitterGroup.size(); ++i) - std::cout << "splitter " << i << ": " << m_vecSplitterTime[i] << ", " - << m_vecSplitterGroup[i] << "\n"; - */ PARALLEL_FOR_NO_WSP_CHECK() for (int64_t iws = 0; iws < int64_t(numberOfSpectra); ++iws) { @@ -1755,150 +1727,9 @@ void FilterEvents::filterEventsByVectorSplitters(double progressamount) { max_target_index = *target_iter; } - // convert vector of int64 to Time - std::vector split_datetime_vec(m_vecSplitterTime.size()); - for (size_t i = 0; i < m_vecSplitterTime.size(); ++i) { - DateAndTime split_time(m_vecSplitterTime[i]); - split_datetime_vec[i] = split_time; - } - - for (auto property : m_eventWS->run().getProperties()) { - // insert 0 even if it is empty for contructing a vector - g_log.debug() << "Process sample log" << property->name() << "\n"; - TimeSeriesProperty *dbl_prop = - dynamic_cast *>(property); - TimeSeriesProperty *int_prop = - dynamic_cast *>(property); - if (dbl_prop) { - std::vector *> output_vector; - for (int tindex = 0; tindex <= max_target_index; ++tindex) { - TimeSeriesProperty *new_property = - new TimeSeriesProperty(dbl_prop->name()); - output_vector.push_back(new_property); - } - - // split - dbl_prop->splitByTimeVector(split_datetime_vec, m_vecSplitterGroup, - output_vector); - - // set to output workspace - for (int tindex = 0; tindex <= max_target_index; ++tindex) { - // find output workspace - std::map::iterator wsiter; - wsiter = m_outputWorkspacesMap.find(tindex); - if (wsiter == m_outputWorkspacesMap.end()) { - ; - // g_log.error() << "Workspace target (" << tindex - // << ") does not have workspace associated." - // << "\n"; - } else { - DataObjects::EventWorkspace_sptr ws_i = wsiter->second; - ws_i->mutableRun().addProperty(output_vector[tindex], true); - } - } - - } else if (int_prop) { - // integer log - std::vector *> output_vector; - for (int tindex = 0; tindex <= max_target_index; ++tindex) { - TimeSeriesProperty *new_property = - new TimeSeriesProperty(int_prop->name()); - output_vector.push_back(new_property); - } - - // split - int_prop->splitByTimeVector(split_datetime_vec, m_vecSplitterGroup, - output_vector); - - // set to output workspace - for (int tindex = 0; tindex <= max_target_index; ++tindex) { - // find output workspace - std::map::iterator wsiter; - wsiter = m_outputWorkspacesMap.find(tindex); - if (wsiter == m_outputWorkspacesMap.end()) { - g_log.error() << "Workspace target (" << tindex - << ") does not have workspace associated." - << "\n"; - } else { - DataObjects::EventWorkspace_sptr ws_i = wsiter->second; - ws_i->mutableRun().addProperty(output_vector[tindex], true); - } - } - } else { - // TODO:FIXME - Copy the prperty! - // set to output workspace ??? -- may not be needed! as the way how output - // workspace is created - } - } - - for (int tindex = 0; tindex <= max_target_index; ++tindex) { - // set to output workspace - for (int tindex = 0; tindex <= max_target_index; ++tindex) { - // find output workspace - std::map::iterator wsiter; - wsiter = m_outputWorkspacesMap.find(tindex); - if (wsiter == m_outputWorkspacesMap.end()) { - g_log.error() << "Workspace target (" << tindex - << ") does not have workspace associated." - << "\n"; - } else { - DataObjects::EventWorkspace_sptr ws_i = wsiter->second; - ws_i->mutableRun().integrateProtonCharge(); - } - } - } - return; } -///** Generate splitters for specified workspace index as a subset of -// * m_splitters -// */ -//Kernel::TimeSplitterType FilterEvents::generateSplitters(int wsindex) { -// Kernel::TimeSplitterType splitters; -// for (const auto &splitter : m_splitters) { -// int index = splitter.index(); -// if (index == wsindex) { -// splitters.push_back(splitter); -// } -// } -// return splitters; -//} - -///** Split a log by splitters -// */ -//void FilterEvents::splitLog(EventWorkspace_sptr eventws, std::string logname, -// TimeSplitterType &splitters) { -// // cast property to both double TimeSeriesProperty and IntSeriesProperty -// Kernel::TimeSeriesProperty *dbl_prop = -// dynamic_cast *>( -// eventws->mutableRun().getProperty(logname)); -// Kernel::TimeSeriesProperty *int_prop = -// dynamic_cast *>( -// eventws->mutableRun().getProperty(logname)); - -// if (!dbl_prop && !int_prop) { -// std::stringstream errmsg; -// errmsg << "Log " << logname -// << " is not TimeSeriesProperty or TimeSeriesProperty. " -// << "Unable to split."; -// throw std::runtime_error(errmsg.str()); -// } else { -// for (const auto &split : splitters) { -// g_log.debug() << "Workspace " << eventws->getName() << ": " -// << "log name = " << logname -// << ", duration = " << split.duration() << " from " -// << split.start() << " to " << split.stop() << ".\n"; -// } - -// // split log -// if (dbl_prop) -// dbl_prop->filterByTimes(splitters); -// else -// int_prop->filterByTimes(splitters); -// } -//} - //---------------------------------------------------------------------------------------------- /** Generate a vector of integer time series property for each splitter * corresponding to each target (in integer) @@ -1968,9 +1799,6 @@ void FilterEvents::generateSplitterTSP( // add run stop time as a new entry DateAndTime stop_time(m_vecSplitterTime[igrp + 1]); curr_tsp->addValue(stop_time, 0); - - // g_log.warning() << "Add " << "i_group " << igrp << " to i_target " << - // itarget << "\n"; } return; @@ -2078,9 +1906,11 @@ std::vector FilterEvents::getTimeSeriesLogNames() { dynamic_cast *>(ip); Kernel::TimeSeriesProperty *inttimeprop = dynamic_cast *>(ip); + Kernel::TimeSeriesProperty *booltimeprop = + dynamic_cast *>(ip); // append to vector if it is either double TimeSeries or int TimeSeries - if (dbltimeprop || inttimeprop) { + if (dbltimeprop || inttimeprop || booltimeprop) { std::string pname = ip->name(); lognames.push_back(pname); } From d4565ce6d177c31c445d72f702f07168a0ca628c Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Mon, 5 Jun 2017 12:15:02 -0400 Subject: [PATCH 03/18] Refs #19406. Fixed clang-format. --- Framework/Algorithms/src/FilterEvents.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index 93b40a2a6b3d..d65d11c37077 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -1665,7 +1665,6 @@ void FilterEvents::filterEventsByVectorSplitters(double progressamount) { "by pulse time."); } - PARALLEL_FOR_NO_WSP_CHECK() for (int64_t iws = 0; iws < int64_t(numberOfSpectra); ++iws) { PARALLEL_START_INTERUPT_REGION From 0ffdddde2d109ddc240e5bfcc7d2bebbe2ec35de Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 6 Jun 2017 07:30:53 -0400 Subject: [PATCH 04/18] Refs #19406. Removing output properties if grouping. --- Framework/Algorithms/src/FilterEvents.cpp | 86 ++++++++++++++--------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index d65d11c37077..ffb42c28eef4 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -1162,18 +1162,19 @@ void FilterEvents::createOutputWorkspaces() { m_wsNames.push_back(wsname.str()); // Set (property) to output workspace and set to ADS - // TODO/ISSUE/NOW - If grouping workspace later, then there is no need to - // create these output properties - declareProperty( - Kernel::make_unique< - API::WorkspaceProperty>( - propertynamess.str(), wsname.str(), Direction::Output), - "Output"); - setProperty(propertynamess.str(), optws); AnalysisDataService::Instance().addOrReplace(wsname.str(), optws); - ++numoutputws; + // create these output properties + if (!this->m_toGroupWS) { + declareProperty( + Kernel::make_unique< + API::WorkspaceProperty>( + propertynamess.str(), wsname.str(), Direction::Output), + "Output"); + setProperty(propertynamess.str(), optws); + } + ++numoutputws; g_log.debug() << "Created output Workspace of group = " << wsgroup << " Property Name = " << propertynamess.str() << " Workspace name = " << wsname.str() @@ -1251,21 +1252,29 @@ void FilterEvents::createOutputWorkspacesMatrixCase() { // Inserted this pair to map m_wsNames.push_back(wsname.str()); - - // Set (property) to output workspace and set to ADS - declareProperty(Kernel::make_unique< - API::WorkspaceProperty>( - propertynamess.str(), wsname.str(), Direction::Output), - "Output"); - setProperty(propertynamess.str(), optws); AnalysisDataService::Instance().addOrReplace(wsname.str(), optws); g_log.debug() << "Created output Workspace of group = " << wsgroup - << " Property Name = " << propertynamess.str() << " Workspace name = " << wsname.str() << " with Number of events = " << optws->getNumberEvents() << "\n"; + // Set (property) to output workspace and set to ADS + if (m_toGroupWS) + { + declareProperty(Kernel::make_unique< + API::WorkspaceProperty>( + propertynamess.str(), wsname.str(), Direction::Output), + "Output"); + setProperty(propertynamess.str(), optws); + + g_log.debug() << " Property Name = " << propertynamess.str() << "\n"; + } + else + { + g_log.debug() << "\n"; + } + // Update progress report m_progress = 0.1 + @@ -1325,30 +1334,39 @@ void FilterEvents::createOutputWorkspacesTableSplitterCase() { // TODO/NOW/ISSUE -- How about comment and info? // add to output workspace property - std::stringstream propertynamess; - if (wsgroup < 0) { - propertynamess << "OutputWorkspace_unfiltered"; - } else { - propertynamess << "OutputWorkspace_" << wsgroup; - } // Inserted this pair to map m_wsNames.push_back(wsname.str()); // Set (property) to output workspace and set to ADS - declareProperty(Kernel::make_unique< - API::WorkspaceProperty>( - propertynamess.str(), wsname.str(), Direction::Output), - "Output"); - setProperty(propertynamess.str(), optws); AnalysisDataService::Instance().addOrReplace(wsname.str(), optws); g_log.debug() << "Created output Workspace of group = " << wsgroup - << " Property Name = " << propertynamess.str() << " Workspace name = " << wsname.str() << " with Number of events = " << optws->getNumberEvents() << "\n"; + if (this->m_toGroupWS) + { + std::stringstream propertynamess; + if (wsgroup < 0) { + propertynamess << "OutputWorkspace_unfiltered"; + } else { + propertynamess << "OutputWorkspace_" << wsgroup; + } + declareProperty(Kernel::make_unique< + API::WorkspaceProperty>( + propertynamess.str(), wsname.str(), Direction::Output), + "Output"); + setProperty(propertynamess.str(), optws); + + g_log.debug() << " Property Name = " << propertynamess.str() << "\n"; + } + else + { + g_log.debug() << "\n"; + } + // Update progress report m_progress = 0.1 + @@ -1656,10 +1674,12 @@ void FilterEvents::filterEventsByVectorSplitters(double progressamount) { size_t num_proton_charges = m_eventWS->run().getProperty("proton_charge")->size(); if (num_proton_charges < m_vecSplitterTime.size()) { - // TODO/ISSUE/NOW - Better error message! - throw runtime_error("It is not a good choice to split fast event by " - "pulse time when there are more splitters than pulse " - "times."); + // throw an exception if there more splitters than proton charges + std::stringstream errmsg; + errmsg << "It is not proper to split fast event 'By PulseTime'', when there are " + "more splitters (" << m_vecSplitterTime.size() << ") than pulse time " + "log entries (" << num_proton_charges << ")"; + throw runtime_error(errmsg.str()); } else g_log.warning("User should understand the inaccurancy to filter events " "by pulse time."); From 0f3936aff354098022308260128a9ba7bbe5749d Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 6 Jun 2017 23:04:58 -0400 Subject: [PATCH 05/18] Refs #19406. Enable FilterEvents to throw exception if input. workspace will be replaced by output workspace group. --- Framework/Algorithms/src/FilterEvents.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index ffb42c28eef4..f0780bba3883 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -361,6 +361,14 @@ void FilterEvents::processAlgorithmProperties() { m_toGroupWS = this->getProperty("GroupWorkspaces"); + if (m_toGroupWS && m_outputWSNameBase.compare(m_eventWS->getName()) == 0) + { + std::stringstream errss; + errss << "It is not allowed to group output workspaces into the same name (i..e, OutputWorkspaceBaseName = " + << m_outputWSNameBase << ") as the input workspace to filter events from."; + throw std::invalid_argument(errss.str()); + } + //------------------------------------------------------------------------- // TOF detector/sample correction //------------------------------------------------------------------------- From 8d23f0e3851ed6882b5f909ae1608878a840e3c5 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Wed, 7 Jun 2017 09:51:11 -0400 Subject: [PATCH 06/18] Refs #19406. Fixed an issue with generating splitters. --- Framework/Algorithms/src/FilterEvents.cpp | 97 +++++++------------- Framework/Algorithms/test/FilterEventsTest.h | 19 ++-- Framework/Kernel/src/TimeSeriesProperty.cpp | 6 +- 3 files changed, 52 insertions(+), 70 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index f0780bba3883..a4544e9fef51 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -826,72 +826,45 @@ void FilterEvents::convertSplittersWorkspaceToVectors() { m_vecSplitterGroup.clear(); m_vecSplitterTime.clear(); + // define filter-left target index + int no_filter_index = m_maxTargetIndex + 1; + // convert SplittersWorkspace to a set of pairs which can be sorted - size_t num_rows = this->m_splittersWorkspace->rowCount(); - for (size_t irow = 0; irow < num_rows; ++irow) { - Kernel::SplittingInterval splitter = - m_splittersWorkspace->getSplitter(irow); - if (m_vecSplitterTime.size() == 0 || - splitter.start() > m_vecSplitterTime.back() + TOLERANCE) { - m_vecSplitterTime.push_back(splitter.start().totalNanoseconds()); - m_vecSplitterTime.push_back(splitter.stop().totalNanoseconds()); - // 0 stands for not defined - m_vecSplitterGroup.push_back(0); + size_t num_splitters = m_splitters.size(); + int64_t last_entry_time(0); + + // it is assumed that m_splitters is sorted by time + for (size_t i_splitter = 0; i_splitter < num_splitters; ++i_splitter) { + // get splitter + Kernel::SplittingInterval splitter = m_splitters[i_splitter]; + int64_t start_time_i64 = splitter.start().totalNanoseconds(); + int64_t stop_time_i64 = splitter.stop().totalNanoseconds(); + if (m_vecSplitterTime.size() == 0) { + // first entry: add + m_vecSplitterTime.push_back(start_time_i64); + m_vecSplitterTime.push_back(stop_time_i64); m_vecSplitterGroup.push_back(splitter.index()); - } else if (splitter.start() < m_vecSplitterTime.back() - TOLERANCE) { - // almost same: then add the spliters.stop() only - m_vecSplitterTime.push_back(splitter.stop().totalNanoseconds()); + } else if (abs(last_entry_time - start_time_i64) < TOLERANCE) { + // start time is SAME as last entry + m_vecSplitterTime.push_back(stop_time_i64); + m_vecSplitterGroup.push_back(splitter.index()); + } else if (start_time_i64 > last_entry_time + TOLERANCE) { + // start time is way behind. then add an empty one + m_vecSplitterTime.push_back(start_time_i64); + m_vecSplitterTime.push_back(stop_time_i64); + m_vecSplitterGroup.push_back(no_filter_index); m_vecSplitterGroup.push_back(splitter.index()); } else { - // have to insert the somewhere - std::vector::iterator finditer = - std::lower_bound(m_vecSplitterTime.begin(), m_vecSplitterTime.end(), - splitter.start().totalNanoseconds()); - // get the index - size_t split_index = - static_cast(finditer - m_vecSplitterTime.begin()); - if (*finditer - splitter.start().totalNanoseconds() > TOLERANCE) { - // the start time is before one splitter indicated by *finditer: insert - // both - // check - if (m_vecSplitterGroup[split_index] != UNDEFINED_SPLITTING_TARGET) { - std::stringstream errss; - errss << "Tried to insert splitter [" << splitter.start() << ", " - << splitter.stop() << "] but there is " - << "already a time entry with target " - << m_vecSplitterGroup[split_index] << " inside it."; - throw std::runtime_error(errss.str()); - } - // inset the full set - m_vecSplitterTime.insert(finditer, splitter.stop().totalNanoseconds()); - m_vecSplitterTime.insert(finditer, splitter.start().totalNanoseconds()); - // insert the target - m_vecSplitterGroup.insert(m_vecSplitterGroup.begin() + split_index, - static_cast(UNDEFINED_SPLITTING_TARGET)); - m_vecSplitterGroup.insert(m_vecSplitterGroup.begin() + split_index, - static_cast(splitter.index())); - } else if (*finditer - splitter.start().totalNanoseconds() > -TOLERANCE) { - // the start time is an existing entry - // check - if (m_vecSplitterGroup[split_index] != UNDEFINED_SPLITTING_TARGET) { - std::stringstream errss; - errss << "Tried to insert splitter [" << splitter.start() << ", " - << splitter.stop() << "] but there is " - << "already a time entry with target " - << m_vecSplitterGroup[split_index] << " inside it."; - throw std::runtime_error(errss.str()); - } - // inset the stop time - m_vecSplitterTime.insert(finditer + 1, - splitter.stop().totalNanoseconds()); - // insert the target - m_vecSplitterGroup.insert(m_vecSplitterGroup.begin() + split_index + 1, - splitter.index()); - } else { - throw std::runtime_error("This is not a possible situation!"); - } - } // IF-ELSE to add a new entry - } // END-FOR (add all splitters) + // some impossible situation + std::stringstream errorss; + errorss << "New start time " << start_time_i64 + << " is before last entry's time " << last_entry_time; + throw std::runtime_error(errorss.str()); + } + + // update + last_entry_time = m_vecSplitterTime.back(); + } // END-FOR (add all splitters) return; } diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index 839d0396831c..7f35be9b2b68 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -326,6 +326,7 @@ class FilterEventsTest : public CxxTest::TestSuite { std::vector outputwsnames = filter.getProperty("OutputWorkspaceNames"); for (size_t i = 0; i < outputwsnames.size(); ++i) { + std::cout << "Delete output workspace name: " << outputwsnames[i] << "\n"; AnalysisDataService::Instance().remove(outputwsnames[i]); } @@ -419,7 +420,7 @@ class FilterEventsTest : public CxxTest::TestSuite { //---------------------------------------------------------------------------------------------- /** Test filtering with correction of direct geometry */ - void test_FilterElasticCorrection() { + void Ptest_FilterElasticCorrection() { EventWorkspace_sptr ws = createEventWorkspaceElastic(0, 1000000); AnalysisDataService::Instance().addOrReplace("MockElasticEventWS", ws); TS_ASSERT_EQUALS(ws->getNumberEvents(), 10000); @@ -477,7 +478,7 @@ class FilterEventsTest : public CxxTest::TestSuite { //---------------------------------------------------------------------------------------------- /** Test filtering with correction of direct geometry */ - void test_FilterDGCorrection() { + void Ptest_FilterDGCorrection() { EventWorkspace_sptr ws = createEventWorkspaceDirect(0, 1000000); AnalysisDataService::Instance().addOrReplace("MockDirectEventWS", ws); @@ -528,7 +529,7 @@ class FilterEventsTest : public CxxTest::TestSuite { //---------------------------------------------------------------------------------------------- /** Test filtering with correction to indirect geometry inelastic instrument */ - void test_FilterIndirectGeometryCorrection() { + void Ptest_FilterIndirectGeometryCorrection() { // Create workspaces for filtering EventWorkspace_sptr ws = createEventWorkspaceInDirect(0, 1000000); AnalysisDataService::Instance().addOrReplace("MockIndirectEventWS", ws); @@ -613,7 +614,7 @@ class FilterEventsTest : public CxxTest::TestSuite { 979: 3: 2.65e+08 - 3.65e+08: 2 979: 4: 3.65e+08 - 4.65e+08: 2 */ - void test_FilterRelativeTime() { + void Ptest_FilterRelativeTime() { // Create EventWorkspace and SplittersWorkspace int64_t runstart_i64 = 20000000000; int64_t pulsedt = 100 * 1000 * 1000; @@ -802,7 +803,7 @@ class FilterEventsTest : public CxxTest::TestSuite { * (2) Count events in each output including "-1", the excluded/unselected * events */ - void test_tableSplitter() { + void Ptest_tableSplitter() { // Create EventWorkspace and SplittersWorkspace int64_t runstart_i64 = 20000000000; int64_t pulsedt = 100 * 1000 * 1000; @@ -985,8 +986,14 @@ class FilterEventsTest : public CxxTest::TestSuite { for (int64_t pid = 0; pid < static_cast(numpulses); pid++) { int64_t pulsetime_i64 = pid * pulsedt + runstart.totalNanoseconds(); Kernel::DateAndTime pulsetime(pulsetime_i64); - if (i == 0) + + // add pulse time to proton charge log once and only once + if (i == 0) { pchargeLog->addValue(pulsetime, 1.); + std::cout << "Add proton charge log " << pulsetime.totalNanoseconds() + << "\n"; + } + for (size_t e = 0; e < 10; e++) { double tof = static_cast(e * tofdt / 1000); TofEvent event(tof, pulsetime); diff --git a/Framework/Kernel/src/TimeSeriesProperty.cpp b/Framework/Kernel/src/TimeSeriesProperty.cpp index c1f729520d19..d083496a9529 100644 --- a/Framework/Kernel/src/TimeSeriesProperty.cpp +++ b/Framework/Kernel/src/TimeSeriesProperty.cpp @@ -532,9 +532,11 @@ void TimeSeriesProperty::splitByTimeVector( // check inputs if (splitter_time_vec.size() != target_vec.size() + 1) { std::stringstream errss; - errss << "Input time vector's size " << splitter_time_vec.size() + errss << "Try to split TSP " << this->m_name + << ": Input time vector's size " << splitter_time_vec.size() << " does not match (one more larger than) taget " - "workspace index vector's size " << target_vec.size() << "\n"; + "workspace index vector's size " + << target_vec.size() << "\n"; throw std::runtime_error(errss.str()); } // return if the output vector TimeSeriesProperties is not defined From 262244ad773f1ecc0847274db1ddfd023a807164 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Wed, 7 Jun 2017 10:15:13 -0400 Subject: [PATCH 07/18] Refs #19406. Fixed clang-format. --- Framework/Algorithms/src/FilterEvents.cpp | 52 ++++++++++----------- Framework/Kernel/src/TimeSeriesProperty.cpp | 3 +- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index a4544e9fef51..d60d30c574ae 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -361,11 +361,11 @@ void FilterEvents::processAlgorithmProperties() { m_toGroupWS = this->getProperty("GroupWorkspaces"); - if (m_toGroupWS && m_outputWSNameBase.compare(m_eventWS->getName()) == 0) - { + if (m_toGroupWS && m_outputWSNameBase.compare(m_eventWS->getName()) == 0) { std::stringstream errss; - errss << "It is not allowed to group output workspaces into the same name (i..e, OutputWorkspaceBaseName = " - << m_outputWSNameBase << ") as the input workspace to filter events from."; + errss << "It is not allowed to group output workspaces into the same name " + "(i..e, OutputWorkspaceBaseName = " << m_outputWSNameBase + << ") as the input workspace to filter events from."; throw std::invalid_argument(errss.str()); } @@ -1241,18 +1241,16 @@ void FilterEvents::createOutputWorkspacesMatrixCase() { << "\n"; // Set (property) to output workspace and set to ADS - if (m_toGroupWS) - { - declareProperty(Kernel::make_unique< - API::WorkspaceProperty>( - propertynamess.str(), wsname.str(), Direction::Output), - "Output"); - setProperty(propertynamess.str(), optws); - - g_log.debug() << " Property Name = " << propertynamess.str() << "\n"; - } - else - { + if (m_toGroupWS) { + declareProperty( + Kernel::make_unique< + API::WorkspaceProperty>( + propertynamess.str(), wsname.str(), Direction::Output), + "Output"); + setProperty(propertynamess.str(), optws); + + g_log.debug() << " Property Name = " << propertynamess.str() << "\n"; + } else { g_log.debug() << "\n"; } @@ -1327,24 +1325,22 @@ void FilterEvents::createOutputWorkspacesTableSplitterCase() { << " with Number of events = " << optws->getNumberEvents() << "\n"; - if (this->m_toGroupWS) - { + if (this->m_toGroupWS) { std::stringstream propertynamess; if (wsgroup < 0) { propertynamess << "OutputWorkspace_unfiltered"; } else { propertynamess << "OutputWorkspace_" << wsgroup; } - declareProperty(Kernel::make_unique< - API::WorkspaceProperty>( - propertynamess.str(), wsname.str(), Direction::Output), - "Output"); + declareProperty( + Kernel::make_unique< + API::WorkspaceProperty>( + propertynamess.str(), wsname.str(), Direction::Output), + "Output"); setProperty(propertynamess.str(), optws); g_log.debug() << " Property Name = " << propertynamess.str() << "\n"; - } - else - { + } else { g_log.debug() << "\n"; } @@ -1657,8 +1653,10 @@ void FilterEvents::filterEventsByVectorSplitters(double progressamount) { if (num_proton_charges < m_vecSplitterTime.size()) { // throw an exception if there more splitters than proton charges std::stringstream errmsg; - errmsg << "It is not proper to split fast event 'By PulseTime'', when there are " - "more splitters (" << m_vecSplitterTime.size() << ") than pulse time " + errmsg << "It is not proper to split fast event 'By PulseTime'', when " + "there are " + "more splitters (" << m_vecSplitterTime.size() + << ") than pulse time " "log entries (" << num_proton_charges << ")"; throw runtime_error(errmsg.str()); } else diff --git a/Framework/Kernel/src/TimeSeriesProperty.cpp b/Framework/Kernel/src/TimeSeriesProperty.cpp index d083496a9529..20b2b119f85b 100644 --- a/Framework/Kernel/src/TimeSeriesProperty.cpp +++ b/Framework/Kernel/src/TimeSeriesProperty.cpp @@ -535,8 +535,7 @@ void TimeSeriesProperty::splitByTimeVector( errss << "Try to split TSP " << this->m_name << ": Input time vector's size " << splitter_time_vec.size() << " does not match (one more larger than) taget " - "workspace index vector's size " - << target_vec.size() << "\n"; + "workspace index vector's size " << target_vec.size() << "\n"; throw std::runtime_error(errss.str()); } // return if the output vector TimeSeriesProperties is not defined From 0a63ef87f1108d128a3a72a044e5edecca080558 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 9 Jun 2017 09:28:52 -0400 Subject: [PATCH 08/18] Refs #19406. Made changes to unit tests. --- Framework/Algorithms/src/FilterEvents.cpp | 2 +- Framework/Algorithms/test/FilterEventsTest.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index d60d30c574ae..e1bae393f811 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -474,7 +474,7 @@ void FilterEvents::groupOutputWorkspace() { } //---------------------------------------------------------------------------------------------- -/** Clone the sample logs that will not be split and add all the +/** Clone the sample logs that will not be split, including single-value and add all the * TimeSeriesProperty sample logs * to vectors by their type * @brief FilterEvents::copyNoneSplitLogs diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index 7f35be9b2b68..d4903941fc5a 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -420,7 +420,7 @@ class FilterEventsTest : public CxxTest::TestSuite { //---------------------------------------------------------------------------------------------- /** Test filtering with correction of direct geometry */ - void Ptest_FilterElasticCorrection() { + void test_FilterElasticCorrection() { EventWorkspace_sptr ws = createEventWorkspaceElastic(0, 1000000); AnalysisDataService::Instance().addOrReplace("MockElasticEventWS", ws); TS_ASSERT_EQUALS(ws->getNumberEvents(), 10000); @@ -478,7 +478,7 @@ class FilterEventsTest : public CxxTest::TestSuite { //---------------------------------------------------------------------------------------------- /** Test filtering with correction of direct geometry */ - void Ptest_FilterDGCorrection() { + void test_FilterDGCorrection() { EventWorkspace_sptr ws = createEventWorkspaceDirect(0, 1000000); AnalysisDataService::Instance().addOrReplace("MockDirectEventWS", ws); @@ -529,7 +529,7 @@ class FilterEventsTest : public CxxTest::TestSuite { //---------------------------------------------------------------------------------------------- /** Test filtering with correction to indirect geometry inelastic instrument */ - void Ptest_FilterIndirectGeometryCorrection() { + void test_FilterIndirectGeometryCorrection() { // Create workspaces for filtering EventWorkspace_sptr ws = createEventWorkspaceInDirect(0, 1000000); AnalysisDataService::Instance().addOrReplace("MockIndirectEventWS", ws); @@ -614,7 +614,7 @@ class FilterEventsTest : public CxxTest::TestSuite { 979: 3: 2.65e+08 - 3.65e+08: 2 979: 4: 3.65e+08 - 4.65e+08: 2 */ - void Ptest_FilterRelativeTime() { + void test_FilterRelativeTime() { // Create EventWorkspace and SplittersWorkspace int64_t runstart_i64 = 20000000000; int64_t pulsedt = 100 * 1000 * 1000; @@ -803,7 +803,7 @@ class FilterEventsTest : public CxxTest::TestSuite { * (2) Count events in each output including "-1", the excluded/unselected * events */ - void Ptest_tableSplitter() { + void test_tableSplitter() { // Create EventWorkspace and SplittersWorkspace int64_t runstart_i64 = 20000000000; int64_t pulsedt = 100 * 1000 * 1000; From cf60a8fe4242aa7d741bfb03ce9b0fb83f395fbc Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 9 Jun 2017 09:37:46 -0400 Subject: [PATCH 09/18] Refs #19406. Clang-format. --- Framework/Algorithms/src/FilterEvents.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index e1bae393f811..673c5411b167 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -474,7 +474,8 @@ void FilterEvents::groupOutputWorkspace() { } //---------------------------------------------------------------------------------------------- -/** Clone the sample logs that will not be split, including single-value and add all the +/** Clone the sample logs that will not be split, including single-value and add + * all the * TimeSeriesProperty sample logs * to vectors by their type * @brief FilterEvents::copyNoneSplitLogs From 5ec41e79f8615b9b4b4fb9a12a58e7c1e8832177 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 13 Jun 2017 16:17:39 -0400 Subject: [PATCH 10/18] Refs #19406. Fixed issues with writing info in generate filter. --- .../Algorithms/src/GenerateEventsFilter.cpp | 52 ++++++++++--------- Framework/Algorithms/test/FilterEventsTest.h | 7 +++ 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Framework/Algorithms/src/GenerateEventsFilter.cpp b/Framework/Algorithms/src/GenerateEventsFilter.cpp index cc2ff8a30b3a..e975e741292a 100644 --- a/Framework/Algorithms/src/GenerateEventsFilter.cpp +++ b/Framework/Algorithms/src/GenerateEventsFilter.cpp @@ -386,8 +386,7 @@ void GenerateEventsFilter::setFilterByTimeOnly() { // Default and thus just one interval std::stringstream ss; - ss << "Time Interval From " << m_startTime << " to " << m_stopTime; - + ss << "Time.Interval.From." << m_startTime << ".To." << m_stopTime; addNewTimeFilterSplitter(m_startTime, m_stopTime, wsindex, ss.str()); } else if (vec_timeintervals.size() == 1) { double timeinterval = vec_timeintervals[0]; @@ -409,7 +408,7 @@ void GenerateEventsFilter::setFilterByTimeOnly() { Kernel::DateAndTime t0(curtime_ns); Kernel::DateAndTime tf(nexttime_ns); std::stringstream ss; - ss << "Time Interval From " << t0 << " to " << tf; + ss << "Time.Interval.From." << t0 << ".to." << tf; addNewTimeFilterSplitter(t0, tf, wsindex, ss.str()); @@ -462,7 +461,7 @@ void GenerateEventsFilter::setFilterByTimeOnly() { Kernel::DateAndTime t0(curtime_ns); Kernel::DateAndTime tf(nexttime_ns); std::stringstream ss; - ss << "Time Interval From " << t0 << " to " << tf; + ss << "Time.Interval.From." << t0 << ".to." << tf; addNewTimeFilterSplitter(t0, tf, wsindex, ss.str()); @@ -661,14 +660,14 @@ void GenerateEventsFilter::processSingleValueFilter(double minvalue, API::TableRow row = m_filterInfoWS->appendRow(); std::stringstream ss; - ss << "Log " << m_dblLog->name() << " From " << minvalue << " To " << maxvalue - << " Value-change-direction "; + ss << "Log." << m_dblLog->name() << ".From." << minvalue << ".To." << maxvalue + << ".Value-change-direction:"; if (filterincrease && filterdecrease) { - ss << " both "; + ss << ".both "; } else if (filterincrease) { - ss << " increase"; + ss << ".increase"; } else { - ss << " decrease"; + ss << ".decrease"; } row << 0 << ss.str(); } @@ -718,14 +717,14 @@ void GenerateEventsFilter::processMultipleValueFilters(double minvalue, // Workgroup information std::stringstream ss; - ss << "Log " << m_dblLog->name() << " From " << lowbound << " To " - << upbound << " Value-change-direction "; + ss << "Log." << m_dblLog->name() << ".From." << lowbound << ".To." + << upbound << ".Value-change-direction:"; if (filterincrease && filterdecrease) { - ss << " both "; + ss << "both"; } else if (filterincrease) { - ss << " increase"; + ss << "increase"; } else { - ss << " decrease"; + ss << "decrease"; }; API::TableRow newrow = m_filterInfoWS->appendRow(); newrow << wsindex << ss.str(); @@ -825,15 +824,12 @@ void GenerateEventsFilter::makeFilterBySingleValue( // Initialize control parameters bool lastGood = false; bool isGood = false; - ; time_duration tol = DateAndTime::durationFromSeconds(TimeTolerance); int numgood = 0; DateAndTime lastTime, currT; DateAndTime start, stop; size_t progslot = 0; - string info; - for (int i = 0; i < m_dblLog->size(); i++) { lastTime = currT; // The new entry @@ -862,7 +858,10 @@ void GenerateEventsFilter::makeFilterBySingleValue( stop = currT; } - addNewTimeFilterSplitter(start, stop, wsindex, info); + std::stringstream infoss; + infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max << ".Direction=" << filterIncrease + << filterDecrease; + addNewTimeFilterSplitter(start, stop, wsindex, infoss.str()); // Reset the number of good ones, for next time numgood = 0; @@ -887,7 +886,10 @@ void GenerateEventsFilter::makeFilterBySingleValue( stop = currT - tol; else stop = currT; - addNewTimeFilterSplitter(start, stop, wsindex, info); + std::stringstream infoss; + infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max << ".Direction=" << filterIncrease + << filterDecrease; + addNewTimeFilterSplitter(start, stop, wsindex, infoss.str()); numgood = 0; } } @@ -1540,18 +1542,18 @@ void GenerateEventsFilter::processIntegerValueFilter(int minvalue, int maxvalue, while (logvalue <= maxvalue) { stringstream message; if (logvalue + delta - 1 > logvalue) - message << m_intLog->name() << " = [" << logvalue << ", " + message << m_intLog->name() << "=[" << logvalue << "," << logvalue + delta - 1 << "]"; else - message << m_intLog->name() << " = " << logvalue; + message << m_intLog->name() << "=" << logvalue; - message << ". Value change direction: "; + message << ".Value change direction:"; if (filterIncrease && filterDecrease) - message << "Both."; + message << "Both"; else if (filterIncrease) - message << "Increasing. "; + message << "Increasing"; else if (filterDecrease) - message << "Decreasing. "; + message << "Decreasing"; TableRow newrow = m_filterInfoWS->appendRow(); newrow << wsindex << message.str(); diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index d4903941fc5a..75842dc29ef2 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -954,6 +954,13 @@ class FilterEventsTest : public CxxTest::TestSuite { return; } + // TODO/NOW/ - complete this unit test case + void Utest_excludeSampleLogs() + { + + + } + //---------------------------------------------------------------------------------------------- /** Create an EventWorkspace. This workspace has * @param runstart_i64 : absolute run start time in int64_t format with unit From b1cd3eb178a0ef1fe70c754c06b93ad5acc9bad4 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 13 Jun 2017 22:38:41 -0400 Subject: [PATCH 11/18] Refs #19406. Added 2 unit tests. 3. Add a new unit test for throwing grouping workspaces if name is not vaid 4. Add a new unit test for excluding sample logs --- Framework/Algorithms/test/FilterEventsTest.h | 118 ++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index 75842dc29ef2..c4f0934099b5 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -27,6 +27,18 @@ using namespace Mantid::Geometry; using namespace std; +/* TODO LIST + * 1. Remove all Ptest + * 2. Add a new unit test for grouping workspaces in the end + * 3. Add a new unit test for throwing grouping workspaces if name is not vaid + * 4. Add a new unit test for excluding sample logs + * 5. Parallelizing spliting logs? + * 6. Speed test + * 6.1 with or without splitting logs; + * 6.2 different types of splitters workspaces; + * 6.3 old vs new + */ + class FilterEventsTest : public CxxTest::TestSuite { public: // This pair of boilerplate methods prevent the suite being created statically @@ -954,11 +966,113 @@ class FilterEventsTest : public CxxTest::TestSuite { return; } - // TODO/NOW/ - complete this unit test case - void Utest_excludeSampleLogs() + /** Test the feature to exclude some sample logs to be split and add to child workspaces + * @brief Utest_excludeSampleLogs + */ + void test_excludeSampleLogs() + { + // Create EventWorkspace and SplittersWorkspace + int64_t runstart_i64 = 20000000000; + int64_t pulsedt = 100 * 1000 * 1000; + int64_t tofdt = 10 * 1000 * 1000; + size_t numpulses = 5; + + EventWorkspace_sptr inpWS = + createEventWorkspace(runstart_i64, pulsedt, tofdt, numpulses); + AnalysisDataService::Instance().addOrReplace("Test12", inpWS); + + DataObjects::TableWorkspace_sptr splws = + createTableSplitters(0, pulsedt, tofdt); + AnalysisDataService::Instance().addOrReplace("TableSplitter2", splws); + + FilterEvents filter; + filter.initialize(); + + // Set properties + filter.setProperty("InputWorkspace", "Test12"); + filter.setProperty("OutputWorkspaceBaseName", "FilteredFromTable"); + filter.setProperty("SplitterWorkspace", "TableSplitter2"); + filter.setProperty("RelativeTime", true); + filter.setProperty("OutputWorkspaceIndexedFrom1", true); + filter.setProperty("RelativeTime", true); + + std::vector prop_vec; + prop_vec.push_back("LogB"); + prop_vec.push_back("slow_log_int"); + filter.setProperty("TimeSeriesPropertyLogs", prop_vec); + filter.setProperty("ExcludeSpecifiedLogs", true); + + // Execute + TS_ASSERT_THROWS_NOTHING(filter.execute()); + TS_ASSERT(filter.isExecuted()); + + // Get 3 output workspaces + int numsplittedws = filter.getProperty("NumberOutputWS"); + TS_ASSERT_EQUALS(numsplittedws, 3); + + // check number of sample logs + size_t num_original_logs = inpWS->run().getProperties().size(); + + std::vector outputwsnames = + filter.getProperty("OutputWorkspaceNames"); + for (size_t i = 0; i < outputwsnames.size(); ++i) { + EventWorkspace_sptr childworkspace = + boost::dynamic_pointer_cast( + AnalysisDataService::Instance().retrieve(outputwsnames[i])); + TS_ASSERT(childworkspace); + // there is 1 sample logs that is excluded from propagating to the child workspaces + TS_ASSERT_EQUALS(num_original_logs, childworkspace->run().getProperties().size()+2); + } + + + // clean workspaces + AnalysisDataService::Instance().remove("Test12"); + AnalysisDataService::Instance().remove("TableSplitter2"); + for (size_t i = 0; i < outputwsnames.size(); ++i) { + AnalysisDataService::Instance().remove(outputwsnames[i]); + } + + return; + } + + /** test for the case that the input workspace name is same as output base workspace name + * @brief test_ThrowSameName + */ + void test_ThrowSameName() { + // Create EventWorkspace and SplittersWorkspace + int64_t runstart_i64 = 20000000000; + int64_t pulsedt = 100 * 1000 * 1000; + int64_t tofdt = 10 * 1000 * 1000; + size_t numpulses = 5; + EventWorkspace_sptr inpWS = + createEventWorkspace(runstart_i64, pulsedt, tofdt, numpulses); + AnalysisDataService::Instance().addOrReplace("Test13", inpWS); + + DataObjects::TableWorkspace_sptr splws = + createTableSplitters(0, pulsedt, tofdt); + AnalysisDataService::Instance().addOrReplace("TableSplitter2", splws); + FilterEvents filter; + filter.initialize(); + + // Set properties + filter.setProperty("InputWorkspace", "Test13"); + filter.setProperty("OutputWorkspaceBaseName", "Test13"); + filter.setProperty("SplitterWorkspace", "TableSplitter2"); + filter.setProperty("RelativeTime", true); + filter.setProperty("OutputWorkspaceIndexedFrom1", true); + filter.setProperty("RelativeTime", true); + + // Execute + TS_ASSERT_THROWS_ANYTHING(filter.execute()); + + // clean workspaces + AnalysisDataService::Instance().remove("Test13"); + AnalysisDataService::Instance().remove("TableSplitter2"); + + return; } //---------------------------------------------------------------------------------------------- From b9ecd7c86ab05c0a3eda16cf3bea06dfd4272a5f Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 16 Jun 2017 12:10:08 -0400 Subject: [PATCH 12/18] Refs #19406. Fixed unit tests. --- Framework/Algorithms/src/FilterEvents.cpp | 18 ++++++++-- .../Algorithms/src/GenerateEventsFilter.cpp | 8 ++--- Framework/Algorithms/test/FilterEventsTest.h | 34 +++++++++++-------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index 673c5411b167..e77516957578 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -470,6 +470,13 @@ void FilterEvents::groupOutputWorkspace() { g_log.error() << "Grouping all output workspaces fails.\n"; } + // set the group workspace as output workspace + declareProperty( + make_unique>("OutputWorkspace", "", + Direction::Output), + "Name of the workspace to be created as the output of grouping "); + setProperty("OutputWorkspace", groupws); + return; } @@ -501,6 +508,10 @@ void FilterEvents::copyNoneSplitLogs( dbl_tsp_name_vector.clear(); bool_tsp_name_vector.clear(); + for (size_t i = 0; i < tsp_logs.size(); ++i) + g_log.warning() << "Include/Exclude " << i << ": " << tsp_logs[i] << "\n"; + g_log.warning() << "TSP log set size = " << tsp_logs_set.size() << "\n"; + std::vector prop_vector = m_eventWS->run().getProperties(); for (size_t i = 0; i < prop_vector.size(); ++i) { // get property @@ -518,17 +529,20 @@ void FilterEvents::copyNoneSplitLogs( // check for time series properties if (dbl_prop || int_prop || bool_prop) { // check whether the log is there + g_log.warning() << "Examine '" << name_i + << "'. Excluded listed logs = " << exclude_listed_logs + << "\n"; set_iter = tsp_logs_set.find(name_i); if (exclude_listed_logs && set_iter != tsp_logs_set.end()) { // exclude all the listed tsp logs and this log name is in the set // skip - g_log.information() << "Skip splitting sample log " << name_i << "\n"; + g_log.warning() << "Skip splitting sample log " << name_i << "\n"; continue; } else if (!exclude_listed_logs && set_iter == tsp_logs_set.end()) { // include all the listed tsp logs to split but this log name is NOT in // the set // skip - g_log.information() << "Skip splitting sample log " << name_i << "\n"; + g_log.warning() << "Skip splitting sample log " << name_i << "\n"; continue; } diff --git a/Framework/Algorithms/src/GenerateEventsFilter.cpp b/Framework/Algorithms/src/GenerateEventsFilter.cpp index e975e741292a..66105e23cae7 100644 --- a/Framework/Algorithms/src/GenerateEventsFilter.cpp +++ b/Framework/Algorithms/src/GenerateEventsFilter.cpp @@ -859,8 +859,8 @@ void GenerateEventsFilter::makeFilterBySingleValue( } std::stringstream infoss; - infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max << ".Direction=" << filterIncrease - << filterDecrease; + infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max + << ".Direction=" << filterIncrease << filterDecrease; addNewTimeFilterSplitter(start, stop, wsindex, infoss.str()); // Reset the number of good ones, for next time @@ -887,8 +887,8 @@ void GenerateEventsFilter::makeFilterBySingleValue( else stop = currT; std::stringstream infoss; - infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max << ".Direction=" << filterIncrease - << filterDecrease; + infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max + << ".Direction=" << filterIncrease << filterDecrease; addNewTimeFilterSplitter(start, stop, wsindex, infoss.str()); numgood = 0; } diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index c4f0934099b5..41509d93e7aa 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -28,7 +28,7 @@ using namespace Mantid::Geometry; using namespace std; /* TODO LIST - * 1. Remove all Ptest + * 1. Remove all Ptest * 2. Add a new unit test for grouping workspaces in the end * 3. Add a new unit test for throwing grouping workspaces if name is not vaid * 4. Add a new unit test for excluding sample logs @@ -937,8 +937,6 @@ class FilterEventsTest : public CxxTest::TestSuite { runstart_i64); TS_ASSERT_EQUALS(splitter2->nthValue(2), 0); - // TODO - Find out the correct value of the splitter log 2 - // Check spectrum 3 of workspace 2 EventList elist3 = filteredws2->getSpectrum(3); elist3.sortPulseTimeTOF(); @@ -966,11 +964,11 @@ class FilterEventsTest : public CxxTest::TestSuite { return; } - /** Test the feature to exclude some sample logs to be split and add to child workspaces + /** Test the feature to exclude some sample logs to be split and add to child + * workspaces * @brief Utest_excludeSampleLogs */ - void test_excludeSampleLogs() - { + void test_excludeSampleLogs() { // Create EventWorkspace and SplittersWorkspace int64_t runstart_i64 = 20000000000; int64_t pulsedt = 100 * 1000 * 1000; @@ -998,7 +996,7 @@ class FilterEventsTest : public CxxTest::TestSuite { std::vector prop_vec; prop_vec.push_back("LogB"); - prop_vec.push_back("slow_log_int"); + prop_vec.push_back("slow_int_log"); filter.setProperty("TimeSeriesPropertyLogs", prop_vec); filter.setProperty("ExcludeSpecifiedLogs", true); @@ -1020,11 +1018,16 @@ class FilterEventsTest : public CxxTest::TestSuite { boost::dynamic_pointer_cast( AnalysisDataService::Instance().retrieve(outputwsnames[i])); TS_ASSERT(childworkspace); - // there is 1 sample logs that is excluded from propagating to the child workspaces - TS_ASSERT_EQUALS(num_original_logs, childworkspace->run().getProperties().size()+2); + // there is 1 sample logs that is excluded from propagating to the child + // workspaces. LogB is not TSP, so it won't be excluded even if it is + // listed + // a new TSP splitter is added by FilterEvents. So there will be exactly + // same number, but some different, sample logs in the input and output + // workspaces + TS_ASSERT_EQUALS(num_original_logs, + childworkspace->run().getProperties().size()); } - // clean workspaces AnalysisDataService::Instance().remove("Test12"); AnalysisDataService::Instance().remove("TableSplitter2"); @@ -1035,11 +1038,11 @@ class FilterEventsTest : public CxxTest::TestSuite { return; } - /** test for the case that the input workspace name is same as output base workspace name + /** test for the case that the input workspace name is same as output base + * workspace name * @brief test_ThrowSameName */ - void test_ThrowSameName() - { + void test_ThrowSameName() { // Create EventWorkspace and SplittersWorkspace int64_t runstart_i64 = 20000000000; int64_t pulsedt = 100 * 1000 * 1000; @@ -1064,9 +1067,10 @@ class FilterEventsTest : public CxxTest::TestSuite { filter.setProperty("RelativeTime", true); filter.setProperty("OutputWorkspaceIndexedFrom1", true); filter.setProperty("RelativeTime", true); + filter.setProperty("GroupWorkspaces", true); // Execute - TS_ASSERT_THROWS_ANYTHING(filter.execute()); + TS_ASSERT(!filter.execute()); // clean workspaces AnalysisDataService::Instance().remove("Test13"); @@ -1195,6 +1199,8 @@ class FilterEventsTest : public CxxTest::TestSuite { } // FOR each pulse } // For each bank + eventWS->mutableRun().integrateProtonCharge(); + // double constshift = l1 / sqrt(ei * 2. * PhysicalConstants::meV / // PhysicalConstants::NeutronMass); From 829d10151e45e9fb7abc3b789bec08e15a493cbd Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 16 Jun 2017 14:11:17 -0400 Subject: [PATCH 13/18] Refs #19406. Fixed generate event filter issue. --- .../Algorithms/src/GenerateEventsFilter.cpp | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Framework/Algorithms/src/GenerateEventsFilter.cpp b/Framework/Algorithms/src/GenerateEventsFilter.cpp index 66105e23cae7..c35f00abee63 100644 --- a/Framework/Algorithms/src/GenerateEventsFilter.cpp +++ b/Framework/Algorithms/src/GenerateEventsFilter.cpp @@ -858,10 +858,8 @@ void GenerateEventsFilter::makeFilterBySingleValue( stop = currT; } - std::stringstream infoss; - infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max - << ".Direction=" << filterIncrease << filterDecrease; - addNewTimeFilterSplitter(start, stop, wsindex, infoss.str()); + std::string empty(""); + addNewTimeFilterSplitter(start, stop, wsindex, empty); // Reset the number of good ones, for next time numgood = 0; @@ -886,12 +884,21 @@ void GenerateEventsFilter::makeFilterBySingleValue( stop = currT - tol; else stop = currT; - std::stringstream infoss; - infoss << "Log." << m_dblLog->name() << ".From." << min << ".To." << max - << ".Direction=" << filterIncrease << filterDecrease; - addNewTimeFilterSplitter(start, stop, wsindex, infoss.str()); - numgood = 0; + + std::string empty(""); + addNewTimeFilterSplitter(start, stop, wsindex, empty); } + + // add the row for information table workspace + // std::stringstream infoss; + // infoss << "DaDa Log." << m_dblLog->name() << ".From." << min << ".To." << + // max + // << ".Direction=Increase" << filterIncrease << "DirectionDecrease=" + // << filterDecrease; + // API::TableRow row = m_filterInfoWS->appendRow(); + // row << wsindex << infoss.str(); + + return; } //---------------------------------------------------------------------------------------------- From b49c220081465a6463d1ccf15b4def39254aa637 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Fri, 16 Jun 2017 17:02:56 -0400 Subject: [PATCH 14/18] Refs #19406. Fixed an issue with grouping output workspaces. --- Framework/Algorithms/src/FilterEvents.cpp | 100 ++++--------------- Framework/Algorithms/test/FilterEventsTest.h | 41 ++++++++ 2 files changed, 60 insertions(+), 81 deletions(-) diff --git a/Framework/Algorithms/src/FilterEvents.cpp b/Framework/Algorithms/src/FilterEvents.cpp index e77516957578..9f6b05f04ff7 100644 --- a/Framework/Algorithms/src/FilterEvents.cpp +++ b/Framework/Algorithms/src/FilterEvents.cpp @@ -1,10 +1,11 @@ #include "MantidAlgorithms/FilterEvents.h" #include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/FileProperty.h" -#include "MantidAPI/TableRow.h" -#include "MantidAPI/SpectrumInfo.h" #include "MantidAPI/Run.h" +#include "MantidAPI/SpectrumInfo.h" +#include "MantidAPI/TableRow.h" #include "MantidAPI/WorkspaceFactory.h" +#include "MantidAPI/WorkspaceGroup.h" #include "MantidAPI/WorkspaceProperty.h" #include "MantidAlgorithms/TimeAtSampleStrategyDirect.h" #include "MantidAlgorithms/TimeAtSampleStrategyElastic.h" @@ -13,15 +14,15 @@ #include "MantidDataObjects/TableWorkspace.h" #include "MantidDataObjects/WorkspaceCreation.h" #include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/LogFilter.h" #include "MantidKernel/PhysicalConstants.h" +#include "MantidKernel/Strings.h" #include "MantidKernel/System.h" #include "MantidKernel/TimeSeriesProperty.h" #include "MantidKernel/VisibleWhenProperty.h" -#include "MantidKernel/ArrayProperty.h" -#include "MantidKernel/Strings.h" #include #include @@ -467,15 +468,25 @@ void FilterEvents::groupOutputWorkspace() { groupws->setProperty("OutputWorkspace", groupname); groupws->execute(); if (!groupws->isExecuted()) { - g_log.error() << "Grouping all output workspaces fails.\n"; + g_log.error("Grouping all output workspaces fails."); + return; } // set the group workspace as output workspace declareProperty( - make_unique>("OutputWorkspace", "", - Direction::Output), + make_unique>( + "OutputWorkspace", groupname, Direction::Output), "Name of the workspace to be created as the output of grouping "); - setProperty("OutputWorkspace", groupws); + + AnalysisDataServiceImpl &ads = AnalysisDataService::Instance(); + API::WorkspaceGroup_sptr workspace_group = + boost::dynamic_pointer_cast(ads.retrieve(groupname)); + if (!workspace_group) { + g_log.error( + "Unable to retrieve output workspace from algorithm GroupWorkspaces"); + return; + } + setProperty("OutputWorkspace", workspace_group); return; } @@ -508,10 +519,6 @@ void FilterEvents::copyNoneSplitLogs( dbl_tsp_name_vector.clear(); bool_tsp_name_vector.clear(); - for (size_t i = 0; i < tsp_logs.size(); ++i) - g_log.warning() << "Include/Exclude " << i << ": " << tsp_logs[i] << "\n"; - g_log.warning() << "TSP log set size = " << tsp_logs_set.size() << "\n"; - std::vector prop_vector = m_eventWS->run().getProperties(); for (size_t i = 0; i < prop_vector.size(); ++i) { // get property @@ -529,9 +536,6 @@ void FilterEvents::copyNoneSplitLogs( // check for time series properties if (dbl_prop || int_prop || bool_prop) { // check whether the log is there - g_log.warning() << "Examine '" << name_i - << "'. Excluded listed logs = " << exclude_listed_logs - << "\n"; set_iter = tsp_logs_set.find(name_i); if (exclude_listed_logs && set_iter != tsp_logs_set.end()) { // exclude all the listed tsp logs and this log name is in the set @@ -708,72 +712,6 @@ void FilterEvents::splitTimeSeriesProperty( return; } -//---------------------------------------------------------------------------------------------- -//** Examine whether any spectrum does not have detector -// * Warning message will be written out -// * @brief FilterEvents::examineEventWS -// */ -// void FilterEvents::examineAndSortEventWS() { -// // get event workspace information -// size_t numhist = m_eventWS->getNumberHistograms(); -// m_vecSkip.resize(numhist, false); - -// // check whether any detector is skipped -// if (m_specSkipType == EventFilterSkipNoDetTOFCorr && -// m_tofCorrType == NoneCorrect) { -// // No TOF correction and skip spectrum only if TOF correction is required -// g_log.warning( -// "By user's choice, No spectrum will be skipped even if it has " -// "no detector."); -// } else { -// // check detectors whether there is any of them that will be skipped -// stringstream msgss; -// size_t numskipspec = 0; -// size_t numeventsskip = 0; - -// const auto &spectrumInfo = m_eventWS->spectrumInfo(); -// for (size_t i = 0; i < numhist; ++i) { -// if (!spectrumInfo.hasDetectors(i)) { -// m_vecSkip[i] = true; - -// ++numskipspec; -// const EventList &elist = m_eventWS->getSpectrum(i); -// numeventsskip += elist.getNumberEvents(); -// msgss << i; -// if (numskipspec % 10 == 0) -// msgss << "\n"; -// else -// msgss << ","; -// } -// } // ENDFOR - -// if (numskipspec > 0) { -// g_log.warning() -// << "There are " << numskipspec -// << " spectra that do not have detectors. " -// << "They will be skipped during filtering. There are total " -// << numeventsskip -// << " events in those spectra. \nList of these specta is as below:\n" -// << msgss.str() << "\n"; -// } else { -// g_log.notice("There is no spectrum that does not have detectors."); -// } - -// } // END-IF-ELSE - -// // sort events -// DataObjects::EventSortType sortType = DataObjects::TOF_SORT; -// if (m_filterByPulseTime) -// sortType = DataObjects::PULSETIME_SORT; -// else -// sortType = DataObjects::PULSETIMETOF_SORT; - -// // This runs the SortEvents algorithm in parallel -// m_eventWS->sortAll(sortType, nullptr); - -// return; -//} - //---------------------------------------------------------------------------------------------- /** Purpose: * Convert SplitterWorkspace object to TimeSplitterType (sorted vector) diff --git a/Framework/Algorithms/test/FilterEventsTest.h b/Framework/Algorithms/test/FilterEventsTest.h index 41509d93e7aa..5fbf3326ca60 100644 --- a/Framework/Algorithms/test/FilterEventsTest.h +++ b/Framework/Algorithms/test/FilterEventsTest.h @@ -1079,6 +1079,47 @@ class FilterEventsTest : public CxxTest::TestSuite { return; } + /** test for the case that the input workspace name is same as output base + * workspace name + * @brief test_ThrowSameName + */ + void test_groupWorkspaces() { + // Create EventWorkspace and SplittersWorkspace + int64_t runstart_i64 = 20000000000; + int64_t pulsedt = 100 * 1000 * 1000; + int64_t tofdt = 10 * 1000 * 1000; + size_t numpulses = 5; + + EventWorkspace_sptr inpWS = + createEventWorkspace(runstart_i64, pulsedt, tofdt, numpulses); + AnalysisDataService::Instance().addOrReplace("Test13", inpWS); + + DataObjects::TableWorkspace_sptr splws = + createTableSplitters(0, pulsedt, tofdt); + AnalysisDataService::Instance().addOrReplace("TableSplitter2", splws); + + FilterEvents filter; + filter.initialize(); + + // Set properties + filter.setProperty("InputWorkspace", "Test13"); + filter.setProperty("OutputWorkspaceBaseName", "13"); + filter.setProperty("SplitterWorkspace", "TableSplitter2"); + filter.setProperty("RelativeTime", true); + filter.setProperty("OutputWorkspaceIndexedFrom1", true); + filter.setProperty("RelativeTime", true); + filter.setProperty("GroupWorkspaces", true); + + // Execute + TS_ASSERT(filter.execute()); + + // clean workspaces + AnalysisDataService::Instance().remove("Test13"); + AnalysisDataService::Instance().remove("TableSplitter2"); + + return; + } + //---------------------------------------------------------------------------------------------- /** Create an EventWorkspace. This workspace has * @param runstart_i64 : absolute run start time in int64_t format with unit From 92e2c35cbdff14fba6355f0e764f2095ad8d155c Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 27 Jun 2017 10:36:53 -0400 Subject: [PATCH 15/18] Refs #19406. Updated release note. --- docs/source/release/v3.11.0/framework.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/release/v3.11.0/framework.rst b/docs/source/release/v3.11.0/framework.rst index fa4a9fb9487c..33dfe3b537bc 100644 --- a/docs/source/release/v3.11.0/framework.rst +++ b/docs/source/release/v3.11.0/framework.rst @@ -17,6 +17,7 @@ Improved - :ref:`SetUncertainties ` now provides a "custom" mode, which lets the user specify both an arbitrary error value whose occurences are to be replaced in the input workspace, as well as the value to replace it with. - :ref:`LoadBBY ` is now better at handling sample information. - :ref:`GroupDetectors ` now supports workspaces with detector scans. +- :ref:`FilterEvents ` has refactored on splitting sample logs. Deprecated ########## From 38be65ce2ad46514181949508e1768a46734553c Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Wed, 28 Jun 2017 10:01:50 -0400 Subject: [PATCH 16/18] Refs #19406. Modified reference workspace. For SystemTests.HYSPECReductionTest.HYSPECReductionTest The workspaces did not match: MDHistoWorkspaces have a different signal at index 2067 (0.00173095 vs 0.00173125) --- .../analysis/reference/HYSPECReduction_TIBasEvents.nxs.md5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Testing/SystemTests/tests/analysis/reference/HYSPECReduction_TIBasEvents.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/HYSPECReduction_TIBasEvents.nxs.md5 index fd70306a58e1..a074d5ffb625 100644 --- a/Testing/SystemTests/tests/analysis/reference/HYSPECReduction_TIBasEvents.nxs.md5 +++ b/Testing/SystemTests/tests/analysis/reference/HYSPECReduction_TIBasEvents.nxs.md5 @@ -1 +1 @@ -846f32a2e87499c798ec56418bc5c5ee \ No newline at end of file +0e32c13270b30d346e70002af2fbf9a5 From 3f92717820b8d857911b55181520a72505e43735 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Wed, 19 Jul 2017 10:21:11 -0400 Subject: [PATCH 17/18] Refs #19406. Fixed an error in SNSPowderRedction. --- .../PythonInterface/plugins/algorithms/SNSPowderReduction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py b/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py index 70dcb22f2bb7..6d0f18d2974f 100644 --- a/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py +++ b/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py @@ -1447,7 +1447,7 @@ def _split_workspace(self, raw_ws_name, split_ws_name): self.log().information("SplitterWorkspace = %s, Information Workspace = %s. " % ( split_ws_name, str(self._splitinfotablews))) - base_name = raw_ws_name + base_name = raw_ws_name + '_split' # find out whether the splitters are relative time or epoch time split_ws = AnalysisDataService.retrieve(split_ws_name) @@ -1474,6 +1474,7 @@ def _split_workspace(self, raw_ws_name, split_ws_name): SplitterWorkspace=split_ws_name, GroupWorkspaces=True, RelativeTime=is_relative_time) else: # split with information table + self.log().notice('[DB...BAT] Raw Name: {0}. Base Name: {1}'.format(raw_ws_name, base_name)) api.FilterEvents(InputWorkspace=raw_ws_name, OutputWorkspaceBaseName=base_name, SplitterWorkspace=split_ws_name, InformationWorkspace=str(self._splitinfotablews), GroupWorkspaces=True, RelativeTime=is_relative_time) From 253f331049f7e5bd3dfb6fb0bad68b3ea2bfff20 Mon Sep 17 00:00:00 2001 From: Wenduo Zhou Date: Tue, 25 Jul 2017 09:47:49 -0400 Subject: [PATCH 18/18] Refs #19406. Fixed issues from Martyn's comment. --- .../Algorithms/inc/MantidAlgorithms/FilterEvents.h | 10 +--------- Framework/Algorithms/src/GenerateEventsFilter.cpp | 9 --------- .../plugins/algorithms/SNSPowderReduction.py | 6 +----- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h b/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h index 83455957d738..8ffdd7161b96 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/FilterEvents.h @@ -74,8 +74,6 @@ class DLLExport FilterEvents : public API::Algorithm { } private: - friend struct Mantid::Kernel::CreateUsingNew; - // Implement abstract Algorithm methods void init() override; // Implement abstract Algorithm methods @@ -141,22 +139,16 @@ class DLLExport FilterEvents : public API::Algorithm { /// Run object std::vector getTimeSeriesLogNames(); - // Kernel::TimeSplitterType generateSplitters(int wsindex); - void generateSplitterTSP( std::vector *> &split_tsp_vec); void generateSplitterTSPalpha( std::vector *> &split_tsp_vec); - /// + /// Add time series property 'Splitter' to each child workspace void mapSplitterTSPtoWorkspaces( const std::vector *> &split_tsp_vec); - // void splitTSPLogInPlace(DataObjects::EventWorkspace_sptr eventws, - // std::string logname, - // Kernel::TimeSplitterType &splitters); - void copyNoneSplitLogs( std::vector *> &int_tsp_name_vector, std::vector *> &dbl_tsp_name_vector, diff --git a/Framework/Algorithms/src/GenerateEventsFilter.cpp b/Framework/Algorithms/src/GenerateEventsFilter.cpp index c35f00abee63..806801bedc03 100644 --- a/Framework/Algorithms/src/GenerateEventsFilter.cpp +++ b/Framework/Algorithms/src/GenerateEventsFilter.cpp @@ -889,15 +889,6 @@ void GenerateEventsFilter::makeFilterBySingleValue( addNewTimeFilterSplitter(start, stop, wsindex, empty); } - // add the row for information table workspace - // std::stringstream infoss; - // infoss << "DaDa Log." << m_dblLog->name() << ".From." << min << ".To." << - // max - // << ".Direction=Increase" << filterIncrease << "DirectionDecrease=" - // << filterDecrease; - // API::TableRow row = m_filterInfoWS->appendRow(); - // row << wsindex << infoss.str(); - return; } diff --git a/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py b/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py index 6d0f18d2974f..f1544cfbcc5e 100644 --- a/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py +++ b/Framework/PythonInterface/plugins/algorithms/SNSPowderReduction.py @@ -723,7 +723,7 @@ def _loadAndSum(self, filename_list, outName): # Normalize by current with new name if self._normalisebycurrent is True: - self.log().warning('[SPECIAL DB] Normalize current to workspace %s' % sample_ws_name) + self.log().information('Normalize current to workspace %s' % sample_ws_name) # temp_ws = self.get_workspace(sample_ws_name) if not (is_event_workspace(sample_ws_name) and get_workspace(sample_ws_name).getNumberEvents() == 0): api.NormaliseByCurrent(InputWorkspace=sample_ws_name, @@ -891,9 +891,6 @@ def _focusChunks(self, filename, filter_wall=(0.,0.), # noqa ReductionProperties="__snspowderreduction", **self._focusPos) # logging (ignorable) - #for iws in range(out_ws_c_s.getNumberHistograms()): - # spec = out_ws_c_s.getSpectrum(iws) - # self.log().debug("[DBx131] ws %d: spectrum No = %d. " % (iws, spec.getSpectrumNo())) if is_event_workspace(out_ws_name_chunk_split): self.log().information('After being aligned and focused, workspace %s: Number of events = %d ' 'of chunk %d ' % (out_ws_name_chunk_split, @@ -1474,7 +1471,6 @@ def _split_workspace(self, raw_ws_name, split_ws_name): SplitterWorkspace=split_ws_name, GroupWorkspaces=True, RelativeTime=is_relative_time) else: # split with information table - self.log().notice('[DB...BAT] Raw Name: {0}. Base Name: {1}'.format(raw_ws_name, base_name)) api.FilterEvents(InputWorkspace=raw_ws_name, OutputWorkspaceBaseName=base_name, SplitterWorkspace=split_ws_name, InformationWorkspace=str(self._splitinfotablews), GroupWorkspaces=True, RelativeTime=is_relative_time)