Skip to content

Commit

Permalink
Protect against single-valued time series/filters when filtering logs.
Browse files Browse the repository at this point in the history
Refs #7968
  • Loading branch information
martyngigg committed Sep 21, 2013
1 parent 8e68564 commit fd1f486
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 20 deletions.
36 changes: 20 additions & 16 deletions Code/Mantid/Framework/Kernel/src/TimeSeriesProperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1490,23 +1490,28 @@ namespace Mantid
// 2. Construct mFilter
std::vector<Kernel::DateAndTime> filtertimes = filter->timesAsVector();
std::vector<bool> filtervalues = filter->valuesAsVector();
m_filter.reserve(filtertimes.size()+1);
assert(filtertimes.size() == filtervalues.size());
const size_t nFilterTimes(filtertimes.size());
m_filter.reserve(nFilterTimes+1);

bool lastIsTrue = false;
for (size_t i = 0; i < filtertimes.size(); i ++)
auto fend = filtertimes.end();
auto vit = filtervalues.begin();
for(auto fit = filtertimes.begin(); fit != fend; ++fit)
{
if (filtervalues[i] && !lastIsTrue)
if (*vit && !lastIsTrue)
{
// Get a true in filter but last recorded value is for false
m_filter.push_back(std::make_pair(filtertimes[i], true));
m_filter.push_back(std::make_pair(*fit, true));
lastIsTrue = true;
}
else if (!filtervalues[i] && lastIsTrue)
else if (!(*vit) && lastIsTrue)
{
// Get a False in filter but last recorded value is for TRUE
m_filter.push_back(std::make_pair(filtertimes[i], false));
m_filter.push_back(std::make_pair(*fit, false));
lastIsTrue = false;
}
++vit; // move to next value
}

// 2b) Get a clean finish
Expand All @@ -1515,29 +1520,28 @@ namespace Mantid
DateAndTime lastTime, nextLastT;
if (m_values.back().time() > filtertimes.back())
{
const size_t nvalues(m_values.size());
// Last log time is later than last filter time
lastTime = m_values.back().time();
if ( m_values[m_values.size()-2].time() > filtertimes.back() )
nextLastT = m_values[m_values.size()-2].time();
if ( nvalues > 1 && m_values[nvalues-2].time() > filtertimes.back() )
nextLastT = m_values[nvalues-2].time();
else
nextLastT = filtertimes.back();
}
else
{
// Last log time is no later than last filter time
lastTime = filtertimes.back();
if (m_values.back().time() > filtertimes[filtertimes.size()-1])
{
nextLastT = m_values.back().time();
}
const size_t nfilterValues(filtervalues.size());
// If last-but-one filter time is still later than value then previous is this
// else it is the last value time
if(nfilterValues > 1 && m_values.back().time() > filtertimes[nfilterValues-2])
nextLastT = filtertimes[nfilterValues-2];
else
{
nextLastT = *(filtertimes.rbegin()+1);
}
nextLastT = m_values.back().time();
}

time_duration dtime = lastTime - nextLastT;

m_filter.push_back(std::make_pair(lastTime+dtime, false));
}

Expand Down
28 changes: 24 additions & 4 deletions Code/Mantid/Framework/Kernel/test/TimeSeriesPropertyTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

#include <cxxtest/TestSuite.h>
#include <ctime>
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/PropertyWithValue.h"
#include "MantidKernel/CPUTimer.h"
#include "MantidKernel/DateAndTime.h"
#include "MantidKernel/PropertyWithValue.h"
#include "MantidKernel/TimeSeriesProperty.h"

#include <boost/math/special_functions/fpclassify.hpp>
#include "MantidKernel/CPUTimer.h"
#include "algorithm"
#include <boost/shared_ptr.hpp>
#include <vector>

using namespace Mantid::Kernel;
Expand Down Expand Up @@ -1378,6 +1379,25 @@ class TimeSeriesPropertyTest : public CxxTest::TestSuite
return;
}

void test_filter_with_single_value_in_series()
{
auto p1 = boost::make_shared<TimeSeriesProperty<double>>("SingleValueTSP");
p1->addValue("2007-11-30T16:17:00", 1.5);

auto filterEndsBefore = boost::make_shared<TimeSeriesProperty<bool>>("EndsBefore");
filterEndsBefore->addValue("2007-11-30T16:16:30",false);
filterEndsBefore->addValue("2007-11-30T16:16:58",true);
p1->filterWith(filterEndsBefore.get());
TS_ASSERT_EQUALS(1, p1->size());

p1->clearFilter();
auto filterEndsAfter = boost::make_shared<TimeSeriesProperty<bool>>("EndsAfter");
filterEndsAfter->addValue("2007-11-30T16:16:30",false);
filterEndsAfter->addValue("2007-11-30T16:17:01",true);
p1->filterWith(filterEndsAfter.get());
TS_ASSERT_EQUALS(1, p1->size());
}


/*
* Test filterWith() on different boundary conditions
Expand Down

0 comments on commit fd1f486

Please sign in to comment.