Skip to content

Commit

Permalink
Refs #10069. Corrected run end and log end.
Browse files Browse the repository at this point in the history
1. Run end time is redefined in order not to miss the events in last
pulse;
2. Time series property is extended to run end;

On branch feature/10069_improve_geneventfilter
  (use "git reset HEAD <file>..." to unstage)

      modified:   ../Mantid/Framework/Algorithms/inc/MantidAlgorithms/GenerateEventsFilter.h
      modified:   ../Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp
      modified:   ../Mantid/Framework/Algorithms/test/GenerateEventsFilterTest.h
  • Loading branch information
wdzhou committed Oct 2, 2014
1 parent 89fdb52 commit b7cfc8e
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 20 deletions.
Expand Up @@ -147,9 +147,12 @@ namespace Algorithms
const double &minvalue, const double &maxvalue,
const Kernel::DateAndTime &startT, const Kernel::DateAndTime &stopT, const bool &filterIncrease, const bool &filterDecrease);

/// ??
/// Determine the chaning direction of log value
int determineChangingDirection(int startindex);

/// Find the end of the run
Kernel::DateAndTime findRunEnd();

DataObjects::EventWorkspace_const_sptr m_dataWS;

/// SplitterWorkspace
Expand All @@ -162,6 +165,9 @@ namespace Algorithms
Kernel::DateAndTime m_startTime;
Kernel::DateAndTime m_stopTime;

/// Run end time
Kernel::DateAndTime m_runEndTime;

double m_timeUnitConvertFactorToNS;

Kernel::TimeSeriesProperty<double>* m_dblLog;
Expand Down
96 changes: 88 additions & 8 deletions Code/Mantid/Framework/Algorithms/src/GenerateEventsFilter.cpp
Expand Up @@ -277,10 +277,8 @@ namespace Algorithms

// Obtain run time range
DateAndTime runstarttime = m_dataWS->run().startTime();
/// FIXME Use this simple method may miss the events in the last pulse
Kernel::TimeSeriesProperty<double>* protonchargelog =
dynamic_cast<Kernel::TimeSeriesProperty<double> *>(m_dataWS->run().getProperty("proton_charge"));
Kernel::DateAndTime runendtime = protonchargelog->lastTime();

m_runEndTime = findRunEnd();

// Obtain time unit converter
std::string timeunit = this->getProperty("UnitOfTime");
Expand All @@ -298,7 +296,7 @@ namespace Algorithms
else if (timeunit.compare("Percent") == 0)
{
// (percent of total run time)
int64_t runtime_ns = runendtime.totalNanoseconds()-runstarttime.totalNanoseconds();
int64_t runtime_ns = m_runEndTime.totalNanoseconds()-runstarttime.totalNanoseconds();
double runtimed_ns = static_cast<double>(runtime_ns);
m_timeUnitConvertFactorToNS = 0.01*runtimed_ns;
}
Expand Down Expand Up @@ -339,7 +337,7 @@ namespace Algorithms
if (defaultstop)
{
// Default
m_stopTime = runendtime;
m_stopTime = m_runEndTime;
}
else if (instringformat)
{
Expand All @@ -365,7 +363,7 @@ namespace Algorithms

g_log.information() << "Filter: StartTime = " << m_startTime << ", StopTime = " << m_stopTime
<< "; Run start = " << runstarttime.toISO8601String()
<< ", Run stop = " << runendtime.toISO8601String() << "\n";
<< ", Run stop = " << m_runEndTime.toISO8601String() << "\n";

return;
}
Expand All @@ -383,6 +381,9 @@ namespace Algorithms
// Progress
int64_t totaltime = m_stopTime.totalNanoseconds()-m_startTime.totalNanoseconds();

g_log.warning() << "Filter by time: start @ " << m_startTime.totalNanoseconds() << "; "
<< "stop @ " << m_stopTime.totalNanoseconds() << "\n";

if (singleslot)
{
int wsindex = 0;
Expand Down Expand Up @@ -452,15 +453,17 @@ namespace Algorithms
throw runtime_error(errmsg.str());
}

// Clear duplicate value
// Clear duplicate value and extend to run end
if (m_dblLog)
{
g_log.debug("Attempting to remove duplicates in double series log.");
m_dblLog->addValue(m_runEndTime, 0.);
m_dblLog->eliminateDuplicates();
}
else
{
g_log.debug("Attempting to remove duplicates in integer series log.");
m_intLog->addValue(m_runEndTime, 0);
m_intLog->eliminateDuplicates();
}

Expand Down Expand Up @@ -1866,5 +1869,82 @@ namespace Algorithms
return;
}

//----------------------------------------------------------------------------------------------
/** Find run end time. Here is how the run end time is defined ranked from highest priority
* 1. Run.endTime()
* 2. Last proton charge log time
* 3. Last event time
* In order to consider the events in the last pulse,
* 1. if proton charge does exist, then run end time will be extended by 1 pulse time
* 2. otherwise, extended by 0.1 second (10 Hz)
* Exception: None of the 3 conditions is found to determine run end time
*/
DateAndTime GenerateEventsFilter::findRunEnd()
{
// Try to get the run end from Run object
DateAndTime runendtime(0);
bool norunendset = false;
try
{
runendtime = m_dataWS->run().endTime();
}
catch (std::runtime_error err)
{
norunendset = true;
}

g_log.debug() << "Check point 1 " << "Run end time = " << runendtime << ", no run end set = "
<< norunendset << "\n";

int64_t extended_ns = static_cast<int64_t>(1.0E8);
if (m_dataWS->run().hasProperty("proton_charge"))
{
// Get last proton charge time and compare with run end time
Kernel::TimeSeriesProperty<double>* protonchargelog =
dynamic_cast<Kernel::TimeSeriesProperty<double> *>(m_dataWS->run().getProperty("proton_charge"));

if (protonchargelog->size() > 1)
{
Kernel::DateAndTime tmpendtime = protonchargelog->lastTime();
extended_ns = protonchargelog->nthTime(1).totalNanoseconds() - protonchargelog->nthTime(0).totalNanoseconds();
if (tmpendtime > runendtime)
{
// Use the last proton charge time
runendtime = tmpendtime;
}
norunendset = false;
}

g_log.debug() << "Check point 2A " << " run end time = " << runendtime << "\n";
}
else if (norunendset && m_dataWS->getNumberEvents() > 0)
{
// No proton_charge or run_end: sort events and find the last event
norunendset = false;

for (size_t i = 0; i < m_dataWS->getNumberHistograms(); ++i)
{
const DataObjects::EventList& evlist = m_dataWS->getEventList(i);
if (evlist.getNumberEvents() > 0)
{
// If event list is empty, the returned value may not make any sense
DateAndTime lastpulse = evlist.getPulseTimeMax();
if (lastpulse > runendtime)
runendtime = lastpulse;
}
}
g_log.warning() << "Check point 2B " << " run end time = " << runendtime << "\n";
}

// Check whether run end time is set
if (norunendset)
throw runtime_error("Run end time cannot be determined. ");

// Add 1 second to make sure that no event left behind either last pulse time or last event time
runendtime = DateAndTime(runendtime.totalNanoseconds() + extended_ns);

return runendtime;
}

} // namespace Mantid
} // namespace Algorithms
26 changes: 15 additions & 11 deletions Code/Mantid/Framework/Algorithms/test/GenerateEventsFilterTest.h
Expand Up @@ -109,8 +109,12 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite
*/
void test_genTimeMultipleInterval()
{
// 1. Create input Workspace
// Create input Workspace
DataObjects::EventWorkspace_sptr eventWS = createEventWorkspace();
for (size_t i = 0; i < eventWS->getNumberHistograms(); ++i)
std::cout << "Spectrum " << i << ": max pulse time = " << eventWS->getEventList(i).getPulseTimeMax()
<< " = " << eventWS->getEventList(i).getPulseTimeMin().totalNanoseconds() << "\n";

int64_t timeinterval_ns = 15000;

// 2. Init and set property
Expand All @@ -133,7 +137,7 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite

TS_ASSERT(splittersws);

size_t numintervals = 67;
size_t numintervals = 74;
TS_ASSERT_EQUALS(splittersws->getNumberSplitters(), numintervals);

std::string runstarttimestr = eventWS->run().getProperty("run_start")->value();
Expand All @@ -142,7 +146,7 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite

Kernel::TimeSeriesProperty<double> *protonchargelog =
dynamic_cast<Kernel::TimeSeriesProperty<double>* >(eventWS->run().getProperty("proton_charge"));
Kernel::DateAndTime runstoptime = protonchargelog->lastTime();
Kernel::DateAndTime runstoptime = Kernel::DateAndTime(protonchargelog->lastTime().totalNanoseconds() + 100000);

// b) First interval
Kernel::SplittingInterval splitter0 = splittersws->getSplitter(0);
Expand Down Expand Up @@ -411,20 +415,19 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite
using namespace WorkspaceCreationHelper;
double PI = 3.14159265;

// 1. Empty workspace
// Empty workspace
DataObjects::EventWorkspace_sptr eventws =
WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(2, 2, true);
//eventws->setName("TestWorkspace");

// 2. Run star time
// Run star time
int64_t runstarttime_ns = 3000000000;
int64_t runstoptime_ns = 3001000000;
int64_t pulsetime_ns = 100000;

Kernel::DateAndTime runstarttime(runstarttime_ns);
eventws->mutableRun().addProperty("run_start", runstarttime.toISO8601String());

// 3. Proton charge log
// Proton charge log
Kernel::TimeSeriesProperty<double> *protonchargelog =
new Kernel::TimeSeriesProperty<double>("proton_charge");
int64_t curtime_ns = runstarttime_ns;
Expand All @@ -435,6 +438,7 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite
curtime_ns += pulsetime_ns;
}
eventws->mutableRun().addProperty(protonchargelog, true);
std::cout << "Proton charge log from " << runstarttime_ns << " to " << runstoptime_ns << "\n";

// 4. Sine value log (value record 1/4 of pulse time. it is FAST)
Kernel::TimeSeriesProperty<double> *sinlog = new Kernel::TimeSeriesProperty<double>("FastSineLog");
Expand Down Expand Up @@ -462,6 +466,8 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite
}
eventws->mutableRun().addProperty(coslog, true);

std::cout << "<----------- Number of events = " << eventws->getNumberEvents() << "\n";

return eventws;
}

Expand Down Expand Up @@ -607,7 +613,7 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite
TS_ASSERT(splittersws);

// Check values of output workspace
size_t numintervals = 67;
size_t numintervals = 74;
TS_ASSERT_EQUALS(splittersws->readY(0).size(), numintervals);

std::string runstarttimestr = eventWS->run().getProperty("run_start")->value();
Expand All @@ -616,7 +622,7 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite

Kernel::TimeSeriesProperty<double> *protonchargelog =
dynamic_cast<Kernel::TimeSeriesProperty<double>* >(eventWS->run().getProperty("proton_charge"));
Kernel::DateAndTime runstoptime = protonchargelog->lastTime();
Kernel::DateAndTime runstoptime = Kernel::DateAndTime(protonchargelog->lastTime().totalNanoseconds() + 100000);

// First interval
TS_ASSERT_EQUALS(static_cast<int64_t>(splittersws->readX(0)[0]), runstarttime_ns);
Expand Down Expand Up @@ -890,8 +896,6 @@ class GenerateEventsFilterTest : public CxxTest::TestSuite
*/
void test_genMultipleIntLogValuesFilterMatrixSplitter()
{
std::cout << "\n==== Test Multiple Integer Log Value Filter (Matrix Splitter) ====\n" << std::endl;

// Create input
DataObjects::EventWorkspace_sptr eventWS = createEventWorkspaceIntLog();
AnalysisDataService::Instance().addOrReplace("TestEventWS09", eventWS);
Expand Down

0 comments on commit b7cfc8e

Please sign in to comment.