1 /* 2 * Medical Image Registration ToolKit (MIRTK) 3 * 4 * Copyright 2016 Imperial College London 5 * Copyright 2016 Andreas Schuh 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 #ifndef MIRTK_DataSelection_H 21 #define MIRTK_DataSelection_H 22 23 #include "mirtk/Object.h" 24 25 #include "mirtk/UnorderedSet.h" 26 #include "mirtk/Algorithm.h" 27 28 29 namespace mirtk { namespace data { 30 31 /// Set of selected data point IDs 32 typedef UnorderedSet<int> Selection; 33 34 // ----------------------------------------------------------------------------- 35 /// Base class of data selectors 36 class Selector : public Object 37 { 38 mirtkAbstractMacro(Selector); 39 40 public: 41 42 /// Destructor ~Selector()43 virtual ~Selector() {}; 44 45 /// Run selection query and return IDs of selected data points 46 /// 47 /// \param[in] values Values of the n data points. 48 /// 49 /// \returns Set of IDs of the selected data points. 50 virtual Selection Evaluate(const Array<double> &values) const = 0; 51 }; 52 53 // ----------------------------------------------------------------------------- 54 /// Combine one or more data selection criteria using a logical operator 55 class LogicalOp : public Selector 56 { 57 mirtkAbstractMacro(LogicalOp); 58 59 typedef SharedPtr<const Selector> SelectorPointer; 60 typedef List<SelectorPointer> SelectorList; 61 62 protected: 63 64 /// Individual data selectors 65 mirtkAttributeMacro(SelectorList, Criteria); 66 67 public: 68 69 /// Number of data selection criteria NumberOfCriteria()70 int NumberOfCriteria() const 71 { 72 return static_cast<int>(_Criteria.size()); 73 } 74 75 /// Get n-th data selection criterium Criterium(int i)76 SelectorPointer Criterium(int i) const 77 { 78 auto it = _Criteria.begin(); 79 for (int pos = 0; pos < i; ++pos) ++it; 80 return *it; 81 } 82 83 /// Add data selection criterium Push(const SelectorPointer & criterium)84 void Push(const SelectorPointer &criterium) 85 { 86 _Criteria.push_back(criterium); 87 } 88 }; 89 90 // ----------------------------------------------------------------------------- 91 /// Combine one or more data selection criteria using a logical AND 92 class LogicalAnd : public LogicalOp 93 { 94 mirtkObjectMacro(LogicalAnd); 95 96 public: 97 98 /// Run selection query and return IDs of selected data points Evaluate(const Array<double> & values)99 virtual Selection Evaluate(const Array<double> &values) const 100 { 101 if (_Criteria.empty()) return Selection(); 102 auto criterium = _Criteria.begin(); 103 auto selection = (*criterium)->Evaluate(values); 104 while (++criterium != _Criteria.end()) { 105 selection = Intersection(selection, (*criterium)->Evaluate(values)); 106 } 107 return selection; 108 } 109 }; 110 111 // ----------------------------------------------------------------------------- 112 /// Combine one or more data selection criteria using a logical OR 113 class LogicalOr : public LogicalOp 114 { 115 mirtkObjectMacro(LogicalOr); 116 117 public: 118 119 /// Run selection query and return IDs of selected data points Evaluate(const Array<double> & values)120 virtual Selection Evaluate(const Array<double> &values) const 121 { 122 Selection selection; 123 for (auto criterium : _Criteria) { 124 auto ids = criterium->Evaluate(values); 125 for (auto id : ids) { 126 selection.insert(id); 127 } 128 } 129 return selection; 130 } 131 }; 132 133 // ----------------------------------------------------------------------------- 134 /// Base class of data selection criteria 135 class SelectionCriterium : public Selector 136 { 137 mirtkAbstractMacro(SelectionCriterium); 138 139 public: 140 141 /// Run selection query and return IDs of selected data points Evaluate(const Array<double> & values)142 virtual Selection Evaluate(const Array<double> &values) const 143 { 144 Selection selection; 145 selection.reserve(values.size()); 146 const int n = static_cast<int>(values.size()); 147 for (int id = 0; id < n; ++id) { 148 if (this->Select(values[id])) { 149 selection.insert(id); 150 } 151 } 152 return selection; 153 } 154 155 /// Evaluate criterium for given data value 156 virtual bool Select(double) const = 0; 157 }; 158 159 // ============================================================================= 160 // Data selection criteria 161 // ============================================================================= 162 163 namespace select { 164 165 166 // ----------------------------------------------------------------------------- 167 /// Select data points with a value equal the specified value 168 class Equal : public SelectionCriterium 169 { 170 mirtkObjectMacro(Equal); 171 172 /// Upper data value threshold 173 mirtkPublicAttributeMacro(double, Value); 174 175 public: 176 177 /// Constructor Equal(double value)178 Equal(double value) : _Value(value) {} 179 180 /// Evaluate criterium for given data value Select(double value)181 virtual bool Select(double value) const 182 { 183 return fequal(value, _Value); 184 } 185 }; 186 187 // ----------------------------------------------------------------------------- 188 /// Select data points a value different from the specified value 189 class NotEqual : public SelectionCriterium 190 { 191 mirtkObjectMacro(NotEqual); 192 193 /// Upper data value threshold 194 mirtkPublicAttributeMacro(double, Value); 195 196 public: 197 198 /// Constructor NotEqual(double value)199 NotEqual(double value) : _Value(value) {} 200 201 /// Evaluate criterium for given data value Select(double value)202 virtual bool Select(double value) const 203 { 204 return !fequal(value, _Value); 205 } 206 }; 207 208 // ----------------------------------------------------------------------------- 209 /// Select data points with a value less than the specified threshold 210 class LessThan : public SelectionCriterium 211 { 212 mirtkObjectMacro(LessThan); 213 214 /// Upper data value threshold 215 mirtkPublicAttributeMacro(double, Threshold); 216 217 public: 218 219 /// Constructor LessThan(double threshold)220 LessThan(double threshold) : _Threshold(threshold) {} 221 222 /// Evaluate criterium for given data value Select(double value)223 virtual bool Select(double value) const 224 { 225 return value < _Threshold; 226 } 227 }; 228 229 // ----------------------------------------------------------------------------- 230 /// Select data points with a value less than or equal the specified threshold 231 class LessOrEqual : public SelectionCriterium 232 { 233 mirtkObjectMacro(LessOrEqual); 234 235 /// Upper data value threshold 236 mirtkPublicAttributeMacro(double, Threshold); 237 238 public: 239 240 /// Constructor LessOrEqual(double threshold)241 LessOrEqual(double threshold) : _Threshold(threshold) {} 242 243 /// Evaluate criterium for given data value Select(double value)244 virtual bool Select(double value) const 245 { 246 return value <= _Threshold; 247 } 248 }; 249 250 // ----------------------------------------------------------------------------- 251 /// Select data points with a value greater than the specified threshold 252 class GreaterThan : public SelectionCriterium 253 { 254 mirtkObjectMacro(GreaterThan); 255 256 /// Lower data value threshold 257 mirtkPublicAttributeMacro(double, Threshold); 258 259 public: 260 261 /// Constructor GreaterThan(double threshold)262 GreaterThan(double threshold) : _Threshold(threshold) {} 263 264 /// Evaluate criterium for given data value Select(double value)265 virtual bool Select(double value) const 266 { 267 return value > _Threshold; 268 } 269 }; 270 271 // ----------------------------------------------------------------------------- 272 /// Select data points with a value greater than or equal the specified threshold 273 class GreaterOrEqual : public SelectionCriterium 274 { 275 mirtkObjectMacro(GreaterOrEqual); 276 277 /// Lower data value threshold 278 mirtkPublicAttributeMacro(double, Threshold); 279 280 public: 281 282 /// Constructor GreaterOrEqual(double threshold)283 GreaterOrEqual(double threshold) : _Threshold(threshold) {} 284 285 /// Evaluate criterium for given data value Select(double value)286 virtual bool Select(double value) const 287 { 288 return value >= _Threshold; 289 } 290 }; 291 292 293 } } } // namespace mirtk::data::select 294 295 #endif // MIRTK_DataSelection_H 296