ImageCodebook.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 #ifndef DRAIN_CODEBOOK
32 #define DRAIN_CODEBOOK
33 
34 
35 #include <drain/Log.h>
36 #include <ostream>
37 #include <vector>
38 #include <map>
39 
40 #include "drain/util/ValueScaling.h"
41 #include "drain/util/LookUp.h"
42 
43 namespace drain
44 {
45 
47 
51 template <class T>
52 class ImageCodeMap : public std::map<double,T> { // : public std::vector<T> {
53 
54 public:
55 
56  typedef std::map<double,T> cont_t;
57  typedef typename cont_t::key_type key_t;
58  typedef typename cont_t::value_type entry_t;
59  //typedef typename cont_t::size_type size_t;
60 
61  // Utility for initializer_list based inits: the threshold values are read in parallel.
62  typedef typename std::list<entry_t> list_t;
63 
64 
66  //ImageCodeMap(size_t n=0, const T & value=T()): cont_t(n, value), separator(0) {
67  ImageCodeMap() : separator(0) {
68  };
69 
70 
71  ImageCodeMap(std::initializer_list<entry_t> l) : cont_t(l), separator(0) {
72  };
73 
74 
76  // ImageCodeMap(const cont_t & v): cont_t(v), separator(0) {
77  ImageCodeMap(const cont_t & map): separator(0) { // COPY?
78  };
79 
80 
83 
84  mutable
85  lookup_t lookUp;
86 
88 
95  lookup_t & createLookUp(const std::type_info & type, const ValueScaling & scaling) const { // todo N?
96 
97  drain::Logger mout(__FILE__, __FUNCTION__);
98 
99  //mout.warn("first entry: " , sprinter(*pal.begin()) );
100  //mout.warn("last entry: " , sprinter(*pal.rbegin()) );
101 
102  lookUp.byteSize = drain::Type::call<drain::sizeGetter>(type);
103 
104  // Todo: add support for signed short and signed char ?
105  if (type == typeid(unsigned short)){ // 1024 entries (not 65536)
106  if ((scaling.scale == 1.0) && (scaling.offset == 0.0)){
107  double first = this->begin()->first;
108  double last = this->rbegin()->first;
109  if ((first >= 0.0) && (last <= 255.0)){
110  lookUp.bitShift = 0;
111  mout.note("short int, but not using 16 bits, coping with 256 entries" );
112  }
113  else
114  lookUp.bitShift = 6;
115  }
116  else
117 
118  lookUp.bitShift = 6; // note => 16 - 6 = 10 bits => 1024 entries
119  }
120  else if (type == typeid(unsigned char)){
121  lookUp.bitShift = 0;
122  }
123  else {
124  mout.note("not supported for type " , drain::Type::getTypeChar(type) );
125  lookUp.byteSize = 0;
126  lookUp.bitShift = 0;
127  lookUp.clear();
128  return lookUp;
129  }
130 
131  const int n = (1 << (lookUp.byteSize*8 - lookUp.bitShift));
132  mout.debug("type=" , drain::Type::getTypeChar(type) , ", creating " , n , " lookup entries" );
133 
134  typename cont_t::const_iterator itLower = this->begin();
135 
136  lookUp.resize(n, itLower);
137 
138  // Signed, because scaling physical values may cause underflow
139  int index, indexLower=0;
140 
142  for (typename cont_t::const_iterator it=this->begin(); it!=this->end(); ++it){
143  //for (const auto & entry: *this){
144 
145  index = static_cast<int>(scaling.inv(it->first));
146 
147  if (index < 0){
148  mout.warn("underflow threshold " , it->first , " mapped to negative index " , index , " (before bitShift), skipping " );
149  continue;
150  }
151 
152  index = (index >> lookUp.bitShift);
153 
154  if (index >= n){
155  mout.warn("overflow: threshold ", it->first, " mapped to index (", index, ") > max (", (n-1), "), skipping " );
156  continue;
157  }
158 
159  if (indexLower < index){
160  mout.debug("adding index range [", indexLower, '-', index, "[ -> (", itLower->first, ") => {", itLower->second, '}');
161  }
162  else {
163  mout.note("accuracy loss: skipped entry [" , index , "] => ", it->first );
164  }
165 
167  for (int i=indexLower; i<index; ++i){
168  lookUp[i] = itLower;
169  }
170 
171  indexLower = index;
172  itLower = it;
173 
174  }
175 
176  index = n;
177  if (indexLower < index){
178  mout.debug() << "padding [" << indexLower << '-' << index << "[ -> \t";
179  mout << '[' << itLower->first << "] // " << itLower->second << mout.endl;
180  }
181  for (int i=indexLower; i<index; ++i){
182  lookUp[i] = itLower;
183  }
184 
185  return lookUp;
186  }
187 
188  // inline
189  typename cont_t::const_iterator retrieve(double d) const {
190 
191  typename cont_t::const_iterator it = this->begin();
192  typename cont_t::const_iterator rit = it; // result
193 
194  while (it != this->end()){
195  if (it->first > d)
196  return rit;
197  rit = it;
198  ++it;
199  }
200 
201  return rit; // may be invalid
202 
203  }
204 
205  // inline
206  typename cont_t::iterator retrieve(double d) {
207 
208  typename cont_t::iterator it = this->begin();
209  typename cont_t::iterator rit = it;
210 
211  while (it != this->end()){
212  if (it->first > d)
213  return rit;
214  rit = it;
215  ++it;
216  }
217 
218  return rit; // may be invalid
219 
220  }
221 
222 
223 
224 
226  /*
227  * \param equal - typically =, :, or -
228  * \param start - typically hyphen or leading parenthesis (, {, [
229  * \param end - typically hyphen or trailing parenthesis ), }, [
230  * \param separator - typically comma or semicolon
231  */
232 
233  // ValueScaling scaling; more like property of image
234 
235  char separator;
236 };
237 
238 /*
239 class ImageCodeEntry {
240 public:
241 
242  virtual inline
243  ~ImageCodeEntry(){};
244 
245  virtual
246  bool empty() const = 0;
247 };
248 */
249 
250 
251 } // drain::
252 
253 #endif
Definition: ImageCodebook.h:52
ImageCodeMap()
Default constructor.
Definition: ImageCodebook.h:67
lookup_t & createLookUp(const std::type_info &type, const ValueScaling &scaling) const
Creates a vector of 256 or 65535 entries for fast retrieval.
Definition: ImageCodebook.h:95
drain::LookUp< typename cont_t::const_iterator > lookup_t
LOOK-UP table.
Definition: ImageCodebook.h:78
ImageCodeMap(const cont_t &map)
Copy constructor //.
Definition: ImageCodebook.h:77
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & note(const TT &... args)
For top-level information.
Definition: Log.h:485
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
Linear scaling and physical range for image intensities.
Definition: ValueScaling.h:64
double & scale
Multiplicative coefficient \i a in: y = ax + b.
Definition: ValueScaling.h:68
double & offset
Additive coefficient \i b in: y = ax + b.
Definition: ValueScaling.h:71
double inv(double y) const
Inverse scaling: given physically meaningful value y, returns the corresponding code value.
Definition: ValueScaling.h:301
Definition: DataSelector.cpp:1277