Commit 0f219c21 authored by Zhou, Wenduo's avatar Zhou, Wenduo
Browse files

Refs #19142. Started to implement new protocol of splitter time.

parent 6da62fa9
......@@ -569,6 +569,88 @@ void FilterEvents::convertSplittersWorkspaceToVectors() {
return;
}
//----------------------------------------------------------------------------------------------
/**
* @brief FilterEvents::processMatrixSplitterWorkspace
* Purpose:
* Convert the splitters in MatrixWorkspace to m_vecSplitterTime and
* m_vecSplitterGroup
* 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_vecSplitterGroup", whose sizes differ by 1.
* - Y values are mapped to integer group index stored in "m_vecSplitterGroup".
* The mapping is recorded in "m_yIndexMap" and "m_wsGroupdYMap"
* "m_maxTargetIndex" is used to register the maximum group index
* Negative Y is defined as "undefined"
* Note: there is NO undefined split region here, while any NEGATIVE Y value is
* defined as "undefined splitter"
*/
void FilterEvents::processMatrixSplitterWorkspace() {
// Check input workspace validity
assert(m_matrixSplitterWS);
auto X = m_matrixSplitterWS->binEdges(0);
auto &Y = m_matrixSplitterWS->y(0);
size_t sizex = X.size();
size_t sizey = Y.size();
// Assign vectors for time comparison
m_vecSplitterTime.assign(X.size(), 0);
m_vecSplitterGroup.assign(Y.size(), -1);
// Transform vector
for (size_t i = 0; i < sizex; ++i) {
m_vecSplitterTime[i] = static_cast<int64_t>(X[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;
}
// process the group
uint32_t max_target_index = 1;
for (size_t i = 0; i < sizey; ++i) {
int y_index = static_cast<int>(Y[i]);
// try to find Y[i] in m_yIndexMap
std::map<int, uint32_t>::iterator mapiter = m_yIndexMap.find(y_index);
if (mapiter == m_yIndexMap.end()) {
// new
// default to 0 as undefined slot.
uint32_t int_target = UNDEFINED_SPLITTING_TARGET;
// if well-defined, then use the current
if (y_index >= 0) {
int_target = max_target_index;
++max_target_index;
}
// un-defined or un-filtered
m_vecSplitterGroup[i] = int_target;
// add to maps and etc.
m_yIndexMap.emplace(y_index, int_target);
m_wsGroupdYMap.emplace(int_target, y_index);
m_targetWorkspaceIndexSet.insert(int_target);
} else {
// this target Y-index has been registered previously
uint32_t target_index = mapiter->second;
m_vecSplitterGroup[i] = target_index;
}
}
// register the max target integer
m_maxTargetIndex = max_target_index - 1;
return;
}
//----------------------------------------------------------------------------------------------
/** process the input splitters given by a TableWorkspace
* The method will transfer the start/stop time to "m_vecSplitterTime"
......@@ -674,88 +756,6 @@ void FilterEvents::processTableSplittersWorkspace() {
return;
}
//----------------------------------------------------------------------------------------------
/**
* @brief FilterEvents::processMatrixSplitterWorkspace
* Purpose:
* Convert the splitters in MatrixWorkspace to m_vecSplitterTime and
* m_vecSplitterGroup
* 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_vecSplitterGroup", whose sizes differ by 1.
* - Y values are mapped to integer group index stored in "m_vecSplitterGroup".
* The mapping is recorded in "m_yIndexMap" and "m_wsGroupdYMap"
* "m_maxTargetIndex" is used to register the maximum group index
* Negative Y is defined as "undefined"
* Note: there is NO undefined split region here, while any NEGATIVE Y value is
* defined as "undefined splitter"
*/
void FilterEvents::processMatrixSplitterWorkspace() {
// Check input workspace validity
assert(m_matrixSplitterWS);
auto X = m_matrixSplitterWS->binEdges(0);
auto &Y = m_matrixSplitterWS->y(0);
size_t sizex = X.size();
size_t sizey = Y.size();
// Assign vectors for time comparison
m_vecSplitterTime.assign(X.size(), 0);
m_vecSplitterGroup.assign(Y.size(), -1);
// Transform vector
for (size_t i = 0; i < sizex; ++i) {
m_vecSplitterTime[i] = static_cast<int64_t>(X[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;
}
// process the group
uint32_t max_target_index = 1;
for (size_t i = 0; i < sizey; ++i) {
int y_index = static_cast<int>(Y[i]);
// try to find Y[i] in m_yIndexMap
std::map<int, uint32_t>::iterator mapiter = m_yIndexMap.find(y_index);
if (mapiter == m_yIndexMap.end()) {
// new
// default to 0 as undefined slot.
uint32_t int_target = UNDEFINED_SPLITTING_TARGET;
// if well-defined, then use the current
if (y_index >= 0) {
int_target = max_target_index;
++max_target_index;
}
// un-defined or un-filtered
m_vecSplitterGroup[i] = int_target;
// add to maps and etc.
m_yIndexMap.emplace(y_index, int_target);
m_wsGroupdYMap.emplace(int_target, y_index);
m_targetWorkspaceIndexSet.insert(int_target);
} else {
// this target Y-index has been registered previously
uint32_t target_index = mapiter->second;
m_vecSplitterGroup[i] = target_index;
}
}
// register the max target integer
m_maxTargetIndex = max_target_index - 1;
return;
}
//----------------------------------------------------------------------------------------------
/** Create a list of EventWorkspace for output in the case that splitters are
* given by
......
......@@ -339,7 +339,8 @@ void GenerateEventsFilter::processInputTime() {
}
// Check start/stop time
if (m_startTime.totalNanoseconds() >= m_stopTime.totalNanoseconds()) {
// if (m_startTime.totalNanoseconds() >= m_stopTime.totalNanoseconds()) {
if (m_startTime >= m_stopTime ){
stringstream errss;
errss << "Input StartTime " << m_startTime.toISO8601String()
<< " is equal or later than "
......@@ -1742,7 +1743,8 @@ void GenerateEventsFilter::generateSplittersInMatrixWorkspace() {
API::WorkspaceFactory::Instance().create("Workspace2D", 1, sizex, sizey);
auto &dataX = m_filterWS->mutableX(0);
for (size_t i = 0; i < sizex; ++i) {
dataX[i] = static_cast<double>(m_vecSplitterTime[i].totalNanoseconds());
// x is in the unit as second
dataX[i] = static_cast<double>(m_vecSplitterTime[i].totalNanoseconds()) * 1.E-9;
}
auto &dataY = m_filterWS->mutableY(0);
......@@ -1779,14 +1781,16 @@ void GenerateEventsFilter::generateSplittersInMatrixWorkspaceParallel() {
size_t index = 0;
for (size_t i = 0; i < numThreads; ++i) {
for (size_t j = 0; j < m_vecGroupIndexSet[i].size(); ++j) {
// x is in the unit as second
dataX[index] =
static_cast<double>(m_vecSplitterTimeSet[i][j].totalNanoseconds());
static_cast<double>(m_vecSplitterTimeSet[i][j].totalNanoseconds()) * 1.E-9;
dataY[index] = static_cast<double>(m_vecGroupIndexSet[i][j]);
++index;
}
}
// x is in the unit as second
dataX[index] = static_cast<double>(
m_vecSplitterTimeSet.back().back().totalNanoseconds());
m_vecSplitterTimeSet.back().back().totalNanoseconds()) * 1.E-9;
}
//----------------------------------------------------------------------------------------------
......
......@@ -600,9 +600,9 @@ public:
TS_ASSERT_EQUALS(splittersws->x(0).size(), 2);
TS_ASSERT_EQUALS(splittersws->y(0).size(), 1);
Kernel::DateAndTime runstart(3000000000);
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[0]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[0]*1.E9),
runstart.totalNanoseconds() + 100);
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[1]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[1]*1.E9),
runstart.totalNanoseconds() + 1000000);
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0)[0]), 0);
......@@ -668,14 +668,14 @@ public:
protonchargelog->lastTime().totalNanoseconds() + 100000);
// First interval
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[0]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[0] * 1.E9),
runstarttime_ns);
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[1]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[1] * 1.E9),
runstarttime_ns + timeinterval_ns);
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0)[0]), 0);
// c) Last interval
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0).back()),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0).back() * 1.E9),
runstoptime.totalNanoseconds());
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0).back()),
numintervals - 1);
......@@ -1010,7 +1010,7 @@ public:
TS_ASSERT_EQUALS(splittersws->y(0).size(), 10);
int64_t factor = static_cast<int64_t>(1.0E9 + 0.5);
TS_ASSERT_DELTA(splittersws->x(0)[0],
TS_ASSERT_DELTA(splittersws->x(0)[0] * 1.E9,
static_cast<double>(11 * factor - 5 * factor / 100),
0.000001);
......@@ -1075,22 +1075,22 @@ public:
protonchargelog->lastTime().totalNanoseconds() + 100000);
// First 3 intervals
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[0]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[0] * 1.E9),
runstarttime_ns);
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[1]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[1] * 1.E9),
runstarttime_ns + timeinterval_ns);
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0)[0]), 0);
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[2]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[2] * 1.E9),
runstarttime_ns + timeinterval_ns * 3);
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0)[1]), 1);
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[3]),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0)[3] * 1.E9),
runstarttime_ns + timeinterval_ns * 6);
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0)[2]), 2);
// Last interval
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0).back()),
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->x(0).back() * 1.E9),
runstoptime.totalNanoseconds());
TS_ASSERT_EQUALS(static_cast<int>(splittersws->y(0).back()),
numintervals - 1);
......@@ -1118,8 +1118,8 @@ public:
for (size_t i = 0; i < vecY.size(); ++i) {
if (vecY[i] >= -0.0) {
// A valid time interval for Splitters
Kernel::DateAndTime tstart(static_cast<int64_t>(vecX[i]));
Kernel::DateAndTime tstop(static_cast<int64_t>(vecX[i + 1]));
Kernel::DateAndTime tstart(static_cast<int64_t>(vecX[i] * 1.E9));
Kernel::DateAndTime tstop(static_cast<int64_t>(vecX[i + 1] * 1.E9));
int wsindex = static_cast<int>(vecY[i]);
Kernel::SplittingInterval ti(tstart, tstop, wsindex);
......
......@@ -20,19 +20,48 @@ Inputs
FilterEvents takes 2 mandatory input Workspaces and 1 optional
Workspace. One of mandatory workspace is the :ref:`EventWorkspace`
where the events are filtered from. The other mandatory workspace is
workspace containing splitters. It can be either a MatrixWorkspace or
workspace containing splitters. It can be a MatrixWorkspace, a TableWorkspace or
a :ref:`SplittersWorkspace <SplittersWorkspace>`.
The optional workspace is a :ref:`TableWorkspace <Table Workspaces>`
for information of splitters.
Workspace containing splitters
==============================
*FilterEvents* accepts three types of workspace that contains event splitters.
- TableWorkspace: a general TableWorkspace with at three columns
- MatrixWorkspace: a 1-spectrum MatrixWorkspace
- SplittersWorkspace: an extended TableWorkspace with restrict definition on start and stop time.
Event splitter
++++++++++++++
An event splitter contains three items, start time, stop time and splitting target (index).
All the events belonged to the same splitting target will be saved to a same output EventWorkspace.
Unit of input splitters
+++++++++++++++++++++++
- MatrixWorkspace: the unit must be second.
- TableWorkspace: the unit must be second.
- SplittersWorkspace: by the definition of SplittersWorkspace, the unit has to be nanosecond.
How to generate input workspace containing splitters
++++++++++++++++++++++++++++++++++++++++++++++++++++
There are two ways to generate
Algorithm :ref:`GenerateEventsFilter <algm-GenerateEventsFilter>`
creates both the :ref:`SplittersWorkspace <SplittersWorkspace>` and
splitter information workspace.
Splitters in relative time
==========================
Splitters in relative time or absolute time
+++++++++++++++++++++++++++++++++++++++++++
As the SplittersWorkspace is in format of :ref:`MatrixWorkspace
<MatrixWorkspace>`, its time, i.e., the value in X vector, can be
......
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