Skip to content

Commit

Permalink
Added method to split events. Refs #8685.
Browse files Browse the repository at this point in the history
Added and tested a method to filter/split events with spliters instored
in vectors.
  • Loading branch information
wdzhou committed Jan 23, 2014
1 parent c774e4c commit e348773
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 36 deletions.
Expand Up @@ -123,7 +123,8 @@ namespace Algorithms
///
std::vector<int> m_vecSplitterGroup;


/// Flag to split sample logs
bool m_splitSampleLogs;
};


Expand Down
55 changes: 37 additions & 18 deletions Code/Mantid/Framework/Algorithms/src/FilterEvents.cpp
Expand Up @@ -86,32 +86,38 @@ namespace Algorithms
new API::WorkspaceProperty<EventWorkspace>("InputWorkspace","",Direction::Input),
"An input event workspace" );

declareProperty(
new API::WorkspaceProperty<API::Workspace>("SplitterWorkspace", "", Direction::Input),
"An input SpilltersWorskpace for filtering");

declareProperty("OutputWorkspaceBaseName", "OutputWorkspace",
"The base name to use for the output workspace" );

declareProperty(new WorkspaceProperty<TableWorkspace>("InformationWorkspace", "", Direction::Input, PropertyMode::Optional),
"Optional output for the information of each splitter workspace index.");

declareProperty(
new API::WorkspaceProperty<API::Workspace>("SplitterWorkspace", "", Direction::Input),
"An input SpilltersWorskpace for filtering");
declareProperty(new WorkspaceProperty<TableWorkspace>("InformationWorkspace", "", Direction::Input,
PropertyMode::Optional),
"Optional output for the information of each splitter workspace index.");

auto tablewsprop = new WorkspaceProperty<TableWorkspace>("DetectorTOFCorrectionWorkspace", "", Direction::Input, PropertyMode::Optional);
auto tablewsprop = new WorkspaceProperty<TableWorkspace>("DetectorTOFCorrectionWorkspace", "", Direction::Input,
PropertyMode::Optional);
declareProperty(tablewsprop, "Name of table workspace containing the log time correction factor for each detector. ");

this->declareProperty("FilterByPulseTime", false,
"Filter the event by its pulse time only for slow sample environment log. This option can make execution of algorithm faster. But it lowers precision.");
declareProperty("FilterByPulseTime", false,
"Filter the event by its pulse time only for slow sample environment log. This option can make execution of algorithm faster. But it lowers precision.");

this->declareProperty("GroupWorkspaces", false,
"Option to group all the output workspaces. Group name will be OutputWorkspaceBaseName.");
declareProperty("GroupWorkspaces", false,
"Option to group all the output workspaces. Group name will be OutputWorkspaceBaseName.");

declareProperty("OutputWorkspaceIndexedFrom1", false, "If selected, the minimum output workspace is indexed from 1 and continuous. ");

declareProperty("NumberOutputWS", 0, "Number of output output workspace splitted. ", Direction::Output);

declareProperty("GenerateTOFCorrection", false, "If this option is true and user does not specify DetectorTOFCorrectionWorkspacel, "
"then the correction will be generated automatically by the instrument geometry. ");

declareProperty("SplitSampleLogs", true, "If selected, all sample logs will be splitted by the "
"event splitters. It is not recommended for fast event log splitters. ");

declareProperty("NumberOutputWS", 0, "Number of output output workspace splitted. ", Direction::Output);


return;
}

Expand Down Expand Up @@ -245,6 +251,8 @@ namespace Algorithms
mWithInfo = false;
else
mWithInfo = true;

m_splitSampleLogs = getProperty("SplitSampleLogs");
}

//----------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -294,6 +302,9 @@ namespace Algorithms
}


//----------------------------------------------------------------------------------------------
/**
*/
void FilterEvents::processMatrixSplitterWorkspace()
{
// Check input workspace validity
Expand Down Expand Up @@ -322,7 +333,6 @@ namespace Algorithms
return;
}


//----------------------------------------------------------------------------------------------
/** Create a list of EventWorkspace for output
*/
Expand Down Expand Up @@ -608,9 +618,16 @@ namespace Algorithms
// FIXME - Turn on parallel


// Finish (1) adding events and splitting the sample logs in each target workspace.
// 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;
}

std::vector<std::string> lognames;
this->getTimeSeriesLogNames(lognames);
g_log.debug() << "[FilterEvents D1214]: Number of TimeSeries Logs = " << lognames.size()
Expand Down Expand Up @@ -714,6 +731,7 @@ namespace Algorithms
// Finish (1) adding events and splitting the sample logs in each target workspace.
progress(0.1+progressamount, "Splitting logs");

#if 0
std::vector<std::string> lognames;
this->getTimeSeriesLogNames(lognames);
g_log.debug() << "[FilterEvents D1214]: Number of TimeSeries Logs = " << lognames.size()
Expand Down Expand Up @@ -752,8 +770,9 @@ namespace Algorithms
progress(0.1+progressamount+outwsindex/numws*0.2, "Splitting logs");
outwsindex += 1.;
}

return;
#else
g_log.notice("Splitters in format of Matrixworkspace are not recommended to split sample logs. ");
#endif

return;
}
Expand Down Expand Up @@ -781,7 +800,7 @@ namespace Algorithms
//----------------------------------------------------------------------------------------------
/** Split a log by splitters
*/
void FilterEvents::splitLog(DataObjects::EventWorkspace_sptr eventws, std::string logname, Kernel::TimeSplitterType& splitters)
void FilterEvents::splitLog(EventWorkspace_sptr eventws, std::string logname, TimeSplitterType& splitters)
{
Kernel::TimeSeriesProperty<double>* prop =
dynamic_cast<Kernel::TimeSeriesProperty<double>* >(eventws->mutableRun().getProperty(logname));
Expand Down
13 changes: 10 additions & 3 deletions Code/Mantid/Framework/DataObjects/src/EventList.cpp
Expand Up @@ -3930,9 +3930,16 @@ namespace DataObjects

// Search in vector
int index = static_cast<int>(lower_bound(vectimes.begin(), vectimes.end(), evabstimens) - vectimes.begin());
if (index == 0)
throw runtime_error("Impossible to have this situation/event is too early ");
int group = vecgroups[index-1];
int group;
if (index == 0 || index == static_cast<int>(vectimes.size()-1))
{
// Event is before first splitter. Put to -1
group = -1;
}
else
{
group = vecgroups[index-1];
}

// Copy event to the proper group
EventList* myOutput = outputs[group];
Expand Down
124 changes: 110 additions & 14 deletions Code/Mantid/Framework/DataObjects/test/EventListTest.h
Expand Up @@ -1453,46 +1453,124 @@ class EventListTest : public CxxTest::TestSuite
}

//-----------------------------------------------------------------------------------------------
void test_splitByTime()
/** Test method to split events by full time (pulse + tof) withtout correction on TOF
*/
void test_splitByFullTime()
{
this->fake_uniform_time_data();
// Create 1000 random events close to SNS's frequency
fake_uniform_time_sns_data();

std::vector< EventList * > outputs;
for (size_t i=0; i<10; i++)
outputs.push_back( new EventList() );
// Output will be 10 event lists
std::map<int, EventList * > outputs;
for (size_t i = 0; i < 10; i++)
outputs.insert(std::make_pair(i, new EventList()));
outputs.insert(std::make_pair(-1, new EventList()));

// Generate time splitters
TimeSplitterType split;
//Start only at 100

// Start only at 100
for (int i = 1; i < 10; i++)
{
// Reject the odd hundreds pulse times (100-199, 300-399, etc).
if ((i%2) == 0)
split.push_back( SplittingInterval(i*1000000, (i+1)*1000000, i) );
else
split.push_back( SplittingInterval(i*1000000, (i+1)*1000000, -1) );
}

// Do the splitting
el.splitByFullTime(split, outputs, 1.0, false);

//No events in the first ouput 0-99
TS_ASSERT_EQUALS( outputs[0]->getNumberEvents(), 0);

for (int i=1; i<10; i++)
{
//Reject the odd hundreds pulse times (100-199, 300-399, etc).
EventList * myOut = outputs[i];
std::cout << i << " " << myOut->getNumberEvents() << "\n";
if ((i%2) == 0)
split.push_back( SplittingInterval(i*100, (i+1)*100, i) );
{
//Even
TS_ASSERT_EQUALS( myOut->getNumberEvents(), 1);
}
else
split.push_back( SplittingInterval(i*100, (i+1)*100, -1) );
{
//Odd
TS_ASSERT_EQUALS( myOut->getNumberEvents(), 0);
}
}

//Do the splitting
el.splitByTime(split, outputs);
return;
}

//-----------------------------------------------------------------------------------------------
/** Test method to split events by full time (pulse + tof) withtout correction on TOF
* and with vector splitter
*/
void test_splitByFullTimeVectorSplitter()
{
// Create 1000 random events close to SNS's frequency
fake_uniform_time_sns_data();

el.sortPulseTimeTOF();
for (size_t i = 0; i < el.getNumberEvents(); ++i)
{
std::cout << el.getEvent(i).pulseTime() << ", " << el.getEvent(i).tof()
<< ", " << el.getEvent(i).pulseTime().totalNanoseconds() + static_cast<int64_t>(el.getEvent(i).tof()*1000.0) << "\n";
}

// Output will be 10 event lists
std::map<int, EventList * > outputs;
for (size_t i = 0; i < 10; i++)
outputs.insert(std::make_pair(i, new EventList()));
outputs.insert(std::make_pair(-1, new EventList()));

// Generate time splitters
std::vector<int64_t> vec_splitTimes;
std::vector<int> vec_splitGroup;

// Start only at 100
for (int i = 1; i <= 10; i++)
{
vec_splitTimes.push_back(i*1000000);
}
vec_splitGroup.assign(vec_splitTimes.size(), -1);
vec_splitGroup[1] = 2;
vec_splitGroup[3] = 4;
vec_splitGroup[5] = 6;
vec_splitGroup[7] = 8;

for (size_t i = 0; i < vec_splitTimes.size()-1; ++i)
{
std::cout << "F " << vec_splitTimes[i] << ", " << vec_splitTimes[i+1] << ", "
<< vec_splitGroup[i] << "\n";
}

// Do the splitting
el.splitByFullTimeMatrixSplitter(vec_splitTimes, vec_splitGroup, outputs, 1.0, false);


//No events in the first ouput 0-99
TS_ASSERT_EQUALS( outputs[0]->getNumberEvents(), 0);

for (size_t i=1; i<10; i++)
for (int i=1; i<10; i++)
{
EventList * myOut = outputs[i];
//std::cout << i << " " << myOut->getNumberEvents() << "\n";
std::cout << i << " " << myOut->getNumberEvents() << "\n";
if ((i%2) == 0)
{
//Even
TS_ASSERT_EQUALS( myOut->getNumberEvents(), 100);
TS_ASSERT_EQUALS( myOut->getNumberEvents(), 1);
}
else
{
//Odd
TS_ASSERT_EQUALS( myOut->getNumberEvents(), 0);
}
}

return;
}


Expand Down Expand Up @@ -1940,6 +2018,24 @@ class EventListTest : public CxxTest::TestSuite
}
}

//----------------------------------------------------------------------------------------------
/** Fake uniform time data more close to SNS case
*/
void fake_uniform_time_sns_data()
{
//Clear the list
el = EventList();

//Create some mostly-reasonable fake data.
srand(1234); //Fixed random seed
for (int time = 0; time < 1000; time++)
{
//All pulse times from 0 to 999 in seconds
DateAndTime pulsetime(static_cast<int64_t>(time*1000000));
el += TofEvent( rand()%1000, pulsetime ); //Kernel::DateAndTime(time*1.0, 0.0) );
}
}

void fake_data_only_two_times(DateAndTime time1, DateAndTime time2)
{
//Clear the list
Expand Down

0 comments on commit e348773

Please sign in to comment.