Commit 8504a86f authored by Zhou, Wenduo's avatar Zhou, Wenduo
Browse files

Refs #14554. Implemented the new features along with change of doc.

parent 52e2587b
......@@ -81,7 +81,7 @@ private:
void exec();
/// Process user input properties
void processProperties();
void processAlgorithmProperties();
void processSplittersWorkspace();
......@@ -171,6 +171,11 @@ private:
EVENTFILTERSKIP m_specSkipType;
/// Vector for skip information
std::vector<bool> m_vecSkip;
// Flag to have relative time in splitters workspace
bool m_isSplittersRelativeTime;
// Starting time for starting time of event filters
Kernel::DateAndTime m_filterStartTime;
};
} // namespace Algorithms
......
......@@ -43,7 +43,7 @@ FilterEvents::FilterEvents()
m_hasInfoWS(), m_progress(0.), m_outputWSNameBase(), m_toGroupWS(false),
m_vecSplitterTime(), m_vecSplitterGroup(), m_splitSampleLogs(false),
m_useDBSpectrum(false), m_dbWSIndex(-1), m_tofCorrType(),
m_specSkipType(), m_vecSkip() {}
m_specSkipType(), m_vecSkip(), m_isSplittersRelativeTime(false), m_filterStartTime(0) {}
//----------------------------------------------------------------------------------------------
/** Destructor
......@@ -142,6 +142,11 @@ void FilterEvents::init() {
new ArrayProperty<string>("OutputWorkspaceNames", Direction::Output),
"List of output workspaces names");
declareProperty("RelativeTime", false, "Flag to indicate that in the input Matrix splitting workspace,"
"the time indicated by X-vector is relative to either run start time or some indicted time.");
declareProperty("FilterStartTime", "", "Start time for splitters that can be parsed to DateAndTime.");
return;
}
......@@ -150,7 +155,7 @@ void FilterEvents::init() {
*/
void FilterEvents::exec() {
// Process algorithm properties
processProperties();
processAlgorithmProperties();
// Examine workspace for detectors
examineEventWS();
......@@ -221,7 +226,7 @@ void FilterEvents::exec() {
//----------------------------------------------------------------------------------------------
/** Process input properties
*/
void FilterEvents::processProperties() {
void FilterEvents::processAlgorithmProperties() {
m_eventWS = this->getProperty("InputWorkspace");
if (!m_eventWS) {
stringstream errss;
......@@ -305,6 +310,35 @@ void FilterEvents::processProperties() {
else
m_useDBSpectrum = true;
// Splitters are given relative time
m_isSplittersRelativeTime = getProperty("RelativeTime");
if (m_isSplittersRelativeTime)
{
// Using relative time
std::string start_time_str = getProperty("FilterStartTime");
if (start_time_str.size() > 0)
{
// User specifies the filter starting time
Kernel::DateAndTime temp_shift_time(start_time_str);
m_filterStartTime = temp_shift_time;
}
else
{
// Retrieve filter starting time from property run_start as default
if (m_eventWS->run().hasProperty("run_start"))
{
Kernel::DateAndTime temp_shift_time(m_eventWS->run().getProperty("run_start")->value());
m_filterStartTime = temp_shift_time;
}
else
{
throw std::runtime_error("Input event workspace does not have property run_start. "
"User does not specifiy filter start time."
"Splitters cannot be in reltive time.");
}
}
}
return;
}
......@@ -372,8 +406,12 @@ void FilterEvents::examineEventWS() {
}
//----------------------------------------------------------------------------------------------
/** Convert SplitterWorkspace object to TimeSplitterType (sorted vector)
* and create a map for all workspace group number
/** Purpose:
* Convert SplitterWorkspace object to TimeSplitterType (sorted vector)
* and create a map for all workspace group number
* Requirements:
* Gaurantees
* @brief FilterEvents::processSplittersWorkspace
*/
void FilterEvents::processSplittersWorkspace() {
// 1. Init data structure
......@@ -416,15 +454,25 @@ void FilterEvents::processSplittersWorkspace() {
//----------------------------------------------------------------------------------------------
/**
*/
* @brief FilterEvents::processMatrixSplitterWorkspace
* Purpose:
* Convert the splitters in matrix workspace to a vector of splitters
* Requirements:
* m_matrixSplitterWS has valid value
* vecX's size must be one larger than and that of vecY of m_matrixSplitterWS
* Guarantees
* Splitters stored in m_matrixSpliterWS are transformed to
* m_vecSplitterTime and m_workGroupIndexes, which are of same size
*/
void FilterEvents::processMatrixSplitterWorkspace() {
// Check input workspace validity
assert(m_matrixSplitterWS);
const MantidVec &vecX = m_matrixSplitterWS->readX(0);
const MantidVec &vecY = m_matrixSplitterWS->readY(0);
size_t sizex = vecX.size();
size_t sizey = vecY.size();
if (sizex - sizey != 1)
throw runtime_error("Size must be N and N-1.");
assert(sizex - sizey == 1);
// Assign vectors for time comparison
m_vecSplitterTime.assign(vecX.size(), 0);
......@@ -434,6 +482,14 @@ void FilterEvents::processMatrixSplitterWorkspace() {
for (size_t i = 0; i < sizex; ++i) {
m_vecSplitterTime[i] = static_cast<int64_t>(vecX[i]);
}
// shift the splitters' time if applied
if (m_isSplittersRelativeTime)
{
int64_t time_shift_ns = m_filterStartTime.totalNanoseconds();
for (size_t i = 0; i < sizex; ++i)
m_vecSplitterTime[i] += time_shift_ns;
}
for (size_t i = 0; i < sizey; ++i) {
m_vecSplitterGroup[i] = static_cast<int>(vecY[i]);
m_workGroupIndexes.insert(m_vecSplitterGroup[i]);
......
......@@ -538,7 +538,102 @@ public:
return;
}
//----------------------------------------------------------------------------------------------
/** Filter events without any correction and test for splitters in MatrixWorkspace format
* and the time given for splitters is relative
* Event workspace:
* (1) 10 detectors
* (2) Run starts @ 20000000000 seconds
* (3) Pulse length = 100*1000*1000 seconds
* (4) Within one pulse, two consecutive events/neutrons is apart for
*10*1000*1000 seconds
* (5) "Experiment": 5 pulse times. 10 events in each pulse
*
* In this test
* (1) Leave correction table workspace empty
* (2) Count events in each output including "-1", the excluded/unselected
*events
*/
void test_FilterRelativeTime() {
// 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;
DataObjects::EventWorkspace_sptr inpWS =
createEventWorkspace(runstart_i64, pulsedt, tofdt, numpulses);
AnalysisDataService::Instance().addOrReplace("Test10", inpWS);
API::MatrixWorkspace_sptr splws = createMatrixSplitter(0, pulsedt, tofdt);
AnalysisDataService::Instance().addOrReplace("Splitter10", splws);
FilterEvents filter;
filter.initialize();
// Set properties
filter.setProperty("InputWorkspace", "Test10");
filter.setProperty("OutputWorkspaceBaseName", "FilteredWS10");
filter.setProperty("SplitterWorkspace", "Splitter10");
filter.setProperty("RelativeTime", true);
filter.setProperty("OutputWorkspaceIndexedFrom1", true);
// Execute
TS_ASSERT_THROWS_NOTHING(filter.execute());
TS_ASSERT(filter.isExecuted());
// Get output
int numsplittedws = filter.getProperty("NumberOutputWS");
TS_ASSERT_EQUALS(numsplittedws, 3);
// 4.1 Workspace group 0
DataObjects::EventWorkspace_sptr filteredws0 =
boost::dynamic_pointer_cast<DataObjects::EventWorkspace>(
AnalysisDataService::Instance().retrieve("FilteredWS10_1"));
TS_ASSERT(filteredws0);
TS_ASSERT_EQUALS(filteredws0->getNumberHistograms(), 10);
TS_ASSERT_EQUALS(filteredws0->getEventList(0).getNumberEvents(), 4);
// 4.2 Workspace group 1
DataObjects::EventWorkspace_sptr filteredws1 =
boost::dynamic_pointer_cast<DataObjects::EventWorkspace>(
AnalysisDataService::Instance().retrieve("FilteredWS10_2"));
TS_ASSERT(filteredws1);
TS_ASSERT_EQUALS(filteredws1->getEventList(1).getNumberEvents(), 16);
// 4.3 Workspace group 2
DataObjects::EventWorkspace_sptr filteredws2 =
boost::dynamic_pointer_cast<DataObjects::EventWorkspace>(
AnalysisDataService::Instance().retrieve("FilteredWS10_3"));
TS_ASSERT(filteredws2);
TS_ASSERT_EQUALS(filteredws2->getEventList(1).getNumberEvents(), 21);
DataObjects::EventList elist3 = filteredws2->getEventList(3);
elist3.sortPulseTimeTOF();
DataObjects::TofEvent eventmin = elist3.getEvent(0);
TS_ASSERT_EQUALS(eventmin.pulseTime().totalNanoseconds(),
runstart_i64 + pulsedt * 2);
TS_ASSERT_DELTA(eventmin.tof(), 0, 1.0E-4);
DataObjects::TofEvent eventmax = elist3.getEvent(20);
TS_ASSERT_EQUALS(eventmax.pulseTime().totalNanoseconds(),
runstart_i64 + pulsedt * 4);
TS_ASSERT_DELTA(eventmax.tof(), static_cast<double>(tofdt * 6 / 1000),
1.0E-4);
// 5. Clean up
AnalysisDataService::Instance().remove("Test02");
AnalysisDataService::Instance().remove("Splitter02");
std::vector<std::string> outputwsnames =
filter.getProperty("OutputWorkspaceNames");
for (size_t i = 0; i < outputwsnames.size(); ++i) {
std::cout << "Output workspace " << i << ": " << outputwsnames[i] << "\n";
AnalysisDataService::Instance().remove(outputwsnames[i]);
}
return;
}
//----------------------------------------------------------------------------------------------
/** Create an EventWorkspace. This workspace has
* @param runstart_i64 : absolute run start time in int64_t format with unit
......@@ -791,6 +886,61 @@ public:
return splitterws;
}
//----------------------------------------------------------------------------------------------
/** Create a Splitter for output
* Region:
* 0: pulse 0: 0 ~ 3+
* 1: pulse 0: 3+ ~ pulse 1: 9+
* 2: from pulse 2: 0 ~ 6+
* -1: from pulse 2: 6+ ~ 9+
* @brief createMatrixSplitter
* @param runstart_i64 : absolute run start time in int64_t format with unit nanosecond
* @param pulsedt: pulse length in int64_t format with unit nanosecond
* @param tofdt: time interval between 2 adjacent event in same pulse in
* int64_t format of unit nanosecond
* @return
*/
API::MatrixWorkspace_sptr
createMatrixSplitter(int64_t runstart_i64, int64_t pulsedt, int64_t tofdt) {
// Create vectors for the splitters
std::vector<int64_t> time_vec;
std::vector<int> index_vec;
time_vec.push_back(runstart_i64);
// Splitter 0: 0 ~ 3+ (first pulse)
int64_t t1 = runstart_i64 + tofdt * 3 + tofdt / 2;
time_vec.push_back(t1);
index_vec.push_back(0);
// Splitter 1: 3+ ~ 9+ (second pulse)
int64_t t2 = runstart_i64 + pulsedt + tofdt * 9 + tofdt / 2;
time_vec.push_back(t2);
index_vec.push_back(1);
// Splitter 2 and so on: from 3rd pulse, 0 ~ 6+
for (size_t i = 2; i < 5; i++) {
int64_t newT = runstart_i64 + i * pulsedt + 6 * tofdt + tofdt / 2;
time_vec.push_back(newT);
index_vec.push_back(2);
}
// Create the workspace and set it
size_t size_x = time_vec.size();
size_t size_y = index_vec.size();
TS_ASSERT(size_x - size_y == 1);
MatrixWorkspace_sptr splitterws = boost::dynamic_pointer_cast<MatrixWorkspace>(
WorkspaceFactory::Instance().create("Workspace2D", 1, size_x, size_y));
for (size_t ix = 0; ix < size_x; ++ix)
splitterws->dataX(0)[ix] = static_cast<double>(time_vec[ix]);
for (size_t iy = 0; iy < size_y; ++iy)
splitterws->dataY(0)[iy] = static_cast<double>(index_vec[iy]);
return splitterws;
}
//----------------------------------------------------------------------------------------------
/** Create a Splitter for fast fequency log for output
* The splitter is within every pulse. 2 groups of splitters are created.
......
......@@ -15,8 +15,31 @@ This algorithm filters events from an
`SplittersWorkspace <http://www.mantidproject.org/SplittersWorkspace>`_ containing a series of
splitters (i.e., `SplittingIntervals <http://www.mantidproject.org/SplittingInterval>`_).
Output
Inputs
######
Algorithm *FilterEvents* takes 2 mandatory input Workspaces and 1 optional Workspace.
One of mandatory workspace is the EventWorkspace where the events are filtered from.
The other mandatory workspace is workspace containing splitters.
It can be either a MatrixWorkspace or a SplittersWorkspace.
The optional workspace is a TableWorkspace for information of splitters.
Algorithm *GenerateEventsFilter* creates both the splitters' workspace and splitter information workspace.
Splitters in relative time
==========================
As the splitters' workspace is in format of MatrixWorkspace,
its time, i.e., the value in X vector, can be relative time.
Property *RelativeTime* flags that the splitters' time is relative.
Property *FilterStartTime* specifies the starting time of the filter.
Or the shift of time of the splitters.
If it is not specified, then the algorithm will search for sample log *run_start*.
Outputs
#######
The output will be one or multiple workspaces according to the number of
index in splitters. The output workspace name is the combination of
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment