Mantid
Loading...
Searching...
No Matches
LogFilter.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
11
12namespace Mantid::Kernel {
13
14namespace {
15// local name for a time that has been made with the default constructor
16const DateAndTime UNSET_TIME(DateAndTime::GPS_EPOCH);
17// pretend end time for a filter that is open-ended
18const DateAndTime OPEN_END_TIME("2100-Jan-01 00:00:01");
19
21TimeROI toTimeROI(const TimeSeriesProperty<bool> &filter) {
22 if (filter.lastValue() && filter.firstTime() == filter.lastTime())
23 return TimeROI(filter.lastTime(), OPEN_END_TIME);
24 return TimeROI(&filter);
25}
26} // namespace
27
36 : m_prop(), m_filter(std::make_unique<TimeSeriesProperty<bool>>("filter")) {
38}
39
45LogFilter::LogFilter(const Property *prop) : m_filter(std::make_unique<TimeSeriesProperty<bool>>("filter")) {
47}
48
54 : m_filter(std::make_unique<TimeSeriesProperty<bool>>("filter")) {
55 m_prop.reset(convertToTimeSeriesOfDouble(timeSeries));
56}
57
65 // do nothing with empty filter
66 if (filter.size() == 0)
67 return;
68 // a single value of one at default GPS epoch is also ignorable
69 if (filter.size() == 1 && filter.firstTime() == UNSET_TIME)
70 return;
71
72 // clear the filter first
73 if (m_prop) {
74 m_prop->clearFilter();
75 }
76
77 // get a local copy of the values for a check further down
78 const auto values = filter.valuesAsVector();
79
80 // If the filter ends in USE
81 bool filterOpenEnded;
82
83 if (std::find(values.cbegin(), values.cend(), true) == values.cend()) {
84 // reset the filter to empty if the new one is all ignore
85 // this assumes that the filter is non-empty because
86 // that is checked for above
87 filterOpenEnded = false;
88 this->setFilter(TimeROI(), filterOpenEnded);
89 } else if (!m_filter || m_filter->size() == 0) {
90 // clean-up and replace current filter
91 filterOpenEnded = filter.lastValue();
92
93 // TimeROI constructor does a ton of cleanup
94 TimeROI mine = toTimeROI(filter);
95
96 // put the results back into the TimeSeriesProperty
97 this->setFilter(mine, filterOpenEnded);
98 } else {
99 // determine if the current version of things are open-ended
100 filterOpenEnded = (m_filter->lastValue() && filter.lastValue());
101
102 // create a local copy of both filters to add extra values to
103 auto filter1 = m_filter.get();
104 auto filter2 = std::unique_ptr<TimeSeriesProperty<bool>>(filter.clone());
105
106 const DateAndTime time1 = filter1->lastTime();
107 const DateAndTime time2 = filter2->lastTime();
108
109 if (time1 < time2) {
110 filter1->addValue(time2,
111 true); // should be f1->lastValue, but it doesnt
112 // matter for boolean AND
113 } else if (time2 < time1) {
114 filter2->addValue(time1, true);
115 }
116
117 // temporary objects to handle the intersection calculation
118 TimeROI mine = toTimeROI(*filter1);
119 TimeROI theirs = toTimeROI(*filter2);
120 mine.update_intersection(theirs);
121
122 // put the results into the TimeSeriesProperty
123 this->setFilter(mine, filterOpenEnded);
124 }
125
126 // apply the filter to the property
127 if (m_prop) {
128 // create a TimeROI to apply
129 TimeROI timeroi;
130
131 // if the end point is a open, then the last point in the TimeROI needs to be modified to make things work out
132 if (filterOpenEnded) {
133 if (m_filter->size() == 1 && m_filter->lastValue()) {
134 // create a pretend ROI from the start to the year 2100
135 timeroi.addROI(m_filter->lastTime(), OPEN_END_TIME);
136 } else {
137 // default constructor is fine
138 timeroi = TimeROI(m_filter.get());
139 }
140
141 // do a test filtering so the second to last interval can be inspected
142 m_prop->filterWith(timeroi);
143 // determine how far out to adjust the last ROI
144 const auto mysize = m_prop->size();
145 const auto penultimate_interval = m_prop->nthInterval(mysize - 2);
146 const auto ultimate_interval = m_prop->nthInterval(mysize - 1);
147 const auto oldEnd = ultimate_interval.stop();
148 const auto newEnd = ultimate_interval.start() + penultimate_interval.length();
149 // extend or shrink the last ROI depending on which value is bigger
150 if (oldEnd > newEnd)
151 timeroi.addMask(newEnd, ultimate_interval.stop());
152 else if (newEnd > oldEnd)
153 timeroi.addROI(oldEnd, newEnd);
154 // both ends match (lucky guess earlier) so there is nothing to adjust
155 } else {
156 timeroi = TimeROI(m_filter.get());
157 }
158
159 // apply the filter
160 m_prop->filterWith(timeroi);
161 }
162}
163
164//-------------------------------------------------------------------------------------------------
167 if (m_prop)
168 m_prop->clearFilter();
169 m_filter.reset();
170}
171
172//--------------------------------------------------------------------------------------------------
173// Private methods
174//--------------------------------------------------------------------------------------------------
175namespace {
176template <typename SrcType> struct ConvertToTimeSeriesDouble {
177 static FilteredTimeSeriesProperty<double> *apply(const Property *prop) {
178 auto srcTypeSeries = dynamic_cast<const TimeSeriesProperty<SrcType> *>(prop);
179 if (!srcTypeSeries)
180 return nullptr;
181 auto converted = new FilteredTimeSeriesProperty<double>(prop->name());
182 auto pmap = srcTypeSeries->valueAsMap();
183 for (auto it = pmap.begin(); it != pmap.end(); ++it) {
184 converted->addValue(it->first, double(it->second));
185 }
186 return converted;
187 }
188};
189} // namespace
190
199 if (auto doubleSeries = ConvertToTimeSeriesDouble<double>::apply(prop)) {
200 return doubleSeries;
201 } else if (auto doubleSeries = ConvertToTimeSeriesDouble<int>::apply(prop)) {
202 return doubleSeries;
203 } else if (auto doubleSeries = ConvertToTimeSeriesDouble<bool>::apply(prop)) {
204 return doubleSeries;
205 } else {
206 throw std::invalid_argument("LogFilter::convertToTimeSeriesOfDouble - Cannot convert property, \"" + prop->name() +
207 "\", to double series.");
208 }
209}
210
211void LogFilter::setFilter(const TimeROI &roi, const bool filterOpenEnded) {
212 // put the results into the TimeSeriesProperty
213 std::vector<bool> values;
214 std::vector<DateAndTime> times;
215 for (const auto &splitter : roi.toTimeIntervals()) {
216 values.emplace_back(true);
217 values.emplace_back(false);
218 times.emplace_back(splitter.start());
219 times.emplace_back(splitter.stop());
220 }
221 // if both are open ended, remove the ending
222 if (filterOpenEnded) {
223 times.pop_back();
224 values.pop_back();
225 }
226
227 // set as the filter
228 if (!m_filter) {
229 m_filter = std::make_unique<TimeSeriesProperty<bool>>("filter");
230 }
231 m_filter->replaceValues(times, values);
232}
233
234} // namespace Mantid::Kernel
Templated class that defines a filtered time series but still gives access to the original data.
std::unique_ptr< FilteredTimeSeriesProperty< double > > m_prop
Owned pointer to the filtered property.
Definition LogFilter.h:66
void clear()
Clears filters.
const TimeSeriesProperty< bool > * filter() const
Returns a reference to the filter.
Definition LogFilter.h:55
void addFilter(const TimeSeriesProperty< bool > &filter)
Adds a filter using boolean AND.
Definition LogFilter.cpp:64
FilteredTimeSeriesProperty< double > * convertToTimeSeriesOfDouble(const Property *prop)
Converts the given property to a TimeSeriesProperty<double>, throws if invalid.
std::unique_ptr< TimeSeriesProperty< bool > > m_filter
Owned pointer to the filter mask.
Definition LogFilter.h:68
LogFilter()=delete
Disable default constructor.
void setFilter(const TimeROI &roi, const bool filterOpenEnded)
Base class for properties.
Definition Property.h:95
const std::string & name() const
Get the property's name.
Definition Property.cpp:63
TimeROI : Object that holds information about when the time measurement was active.
Definition TimeROI.h:18
void addMask(const std::string &startTime, const std::string &stopTime)
Definition TimeROI.cpp:151
const std::vector< Kernel::TimeInterval > toTimeIntervals() const
This method is to lend itself to helping with transition.
Definition TimeROI.cpp:557
void addROI(const std::string &startTime, const std::string &stopTime)
Definition TimeROI.cpp:76
void update_intersection(const TimeROI &other)
Updates the TimeROI values with the intersection with another TimeROI.
Definition TimeROI.cpp:503
A specialised Property class for holding a series of time-value pairs.
TimeSeriesProperty< TYPE > * clone() const override
"Virtual" copy constructor
int size() const override
Returns the number of values at UNIQUE time intervals in the time series.
std::vector< TYPE > valuesAsVector() const
Return the time series's values (unfiltered) as a vector<TYPE>
Types::Core::DateAndTime firstTime() const
Returns the first time regardless of filter.
TYPE lastValue() const
Returns the last value.
Generate a tableworkspace to store the calibration results.
STL namespace.