ValueScaling.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 IMAGE_SCALING2_H_
32 #define IMAGE_SCALING2_H_ "ImageScaling 0.1, 2017/09 Markus.Peura@fmi.fi"
33 
34 #include <drain/Type.h>
35 #include <drain/TypeUtils.h>
36 #include <drain/UniTuple.h>
37 #include <stddef.h> // size_t
38 
39 #include "Range.h"
40 
41 //#include "Geometry.h"
42 //#include "Coordinates.h"
43 
44 
45 namespace drain
46 {
47 
48 
49 //extern drain::Log iLog;
50 
51 // If the intensities of the image correspond to a physical value (like temperature), this is the recommended way to copy.
52 
54 
64 class ValueScaling : public UniTuple<double,2> { // UniTuple<double,4>{
65 public:
66 
68  double & scale;
69 
71  double & offset;
72 
75 
76 
77  inline
78  ValueScaling(double scale=1.0, double offset = 0.0) : // RANGE ok? double scaleOut=1.0, double offsetOut=0.0) :
79  scale(this->next()), offset(this->next()) //, physRange(this->tuple(), 2)
80  {
81  //setConversionScale(scale, offset, scaleOut, offsetOut);
83  physRange.set(0,0);
84  };
85 
86  inline
87  ValueScaling(double scale, double offset, const drain::Range<double> & range) : //, double scaleOut=1.0, double offsetOut=0.0) :
88  scale(this->next()), offset(this->next()) //, physRange(this->tuple(), 2)
89  {
90  //setConversionScale(scale, offset, scaleOut, offsetOut);
92  physRange.set(range); // TODO tune: scaleOut, offsetOut
93  };
94 
95  inline
96  ValueScaling(const drain::ValueScaling & scaling) :
97  scale(this->next()), offset(this->next()) //, physRange(this->tuple(), 2)
98  {
99  this->assignSequence(scaling);
100  physRange.set(scaling.physRange);
101  };
102 
103  //
104  inline
105  ValueScaling(const drain::UniTuple<double,2> & scaling) :
106  scale(this->next()), offset(this->next())
107  {
108  setScaling(scaling[0], scaling[1]);
109  };
110 
111 
112  // Conversion scaling
113  inline
114  ValueScaling(const drain::ValueScaling & scalingIn, const drain::ValueScaling & scalingOut) :
115  scale(this->next()), offset(this->next())
116  {
117  setConversionScale(scalingIn, scalingOut);
118  // physRange??? intersection / union
119  };
120 
121  virtual inline
122  ~ValueScaling(){};
123 
124 
125  inline
126  ValueScaling & operator=(const drain::ValueScaling & scaling){
127  if (&scaling != this){
128  this->assignSequence(scaling);
129  physRange.set(scaling.physRange);
130  }
131  return *this;
132  }
133 
135  virtual inline
136  void setScaling(double scale, double offset){
137  this->set(scale, offset); // virtual IMPORTANT for channels/view
138  }
139 
140  virtual
141  void setScaling(const ValueScaling & scaling){
142  this->assignSequence(scaling);
143  }
144 
146  virtual inline // LATER: scalingPtr!
147  const ValueScaling & getScaling() const {
148  return *this;
149  }
150 
152  virtual inline // LATER: scalingPtr!
154  return *this;
155  }
156 
157 
158 
160  inline
162  set(1.0, 0.0);
163  }
164 
166 
172  inline
173  void setNormalScale(const std::type_info & t){
174  if (Type::call<drain::typeIsSmallInt>(t))
175  set(1.0/drain::Type::call<drain::typeMax,double>(t), 0.0);
176  else // warn? (esp. for int and long int)
177  set(1.0, 0.0); // absolute scale
178  }
179 
181  inline
182  void setConversionScale(double scale, double offset = 0.0, double scaleOut=1.0, double offsetOut=0.0){
183  set(scale/scaleOut, (offset - offsetOut)/scaleOut);
184  }
185 
187  inline
189  set(s2.scale/s1.scale, (s2.offset-s1.offset) / s1.scale);
190  }
191 
192  //template <typename T>
193  inline
194  void setConversionScale(const Range<double> & r1, const Range<double> & r2){
195  set(r2.width()/r1.width(), r2.min - r2.width()/r1.width()*r1.min);
196  }
197 
199  void setOptimalScale(const std::type_info & t);
200 
201 
203  inline
204  void setPhysicalScale(const std::type_info & t, double min, double max){
205  setPhysicalRange(min, max);
206  setOptimalScale(t);
207  }
208 
210 
213  inline
214  void setPhysicalScale(const std::type_info & t, const drain::ValueScaling & scaling){
216  setOptimalScale(t);
217  };
218 
220  inline
221  const Range<double> & getPhysicalRange() const { // , const std::string &unit ?
222  return physRange;
223  }
224 
226  inline
227  Range<double> & getPhysicalRange() { // , const std::string &unit ?
228  return physRange;
229  }
230 
232  inline
233  void setPhysicalMax(double max){ // dangerous (after min?)
234  setPhysicalRange(0.0, max);
235  }
236 
238  template <class T>
239  inline
240  void setPhysicalRange(const Range<T> &range){ // , const std::string &unit ?
241  physRange.assignSequence(range);
242  }
243 
245  inline
246  void setPhysicalRange(double min, double max){ // , const std::string &unit ?
247  physRange.set(min,max);
248  }
249 
251  inline
252  double getScale() const { return scale; }
253 
255  inline
256  double getOffset() const { return offset; }
257 
259 
262  inline
263  bool isScaled() const {
264  return (scale!=1.0) || (offset!=0.0);
265  }
266 
268  inline
269  double getMinPhys() const {
270  return physRange.min;
271  }
272 
274  inline
275  double getMaxPhys() const {
276  return physRange.max;
277  }
278 
280  inline
281  bool isPhysical() const {
282  return (!physRange.empty());
283  }
284 
286  /* short => float
287  *
288  */
289  //inline
290  void adoptScaling(const drain::ValueScaling & srcScaling, const std::type_info & srcType, const std::type_info & dstType = typeid(void));
291 
292 
294  inline
295  double fwd(double x) const {
296  return scale*x + offset;
297  }
298 
300  inline
301  double inv(double y) const {
302  return (y - offset) / scale;
303  }
304 
305 
306 
307  inline
308  void toStream(std::ostream & ostr) const {
309  ostr << scale << ',' << offset;
310  if (isPhysical())
311  ostr << " [" << physRange << ']';
312  }
313 
314  inline
315  std::string str() const{
316  std::stringstream sstr;
317  toStream(sstr);
318  return sstr.str();
319  }
320 
321 
322 
323 };
324 
325 inline
326 std::ostream & operator<<(std::ostream &ostr, const drain::ValueScaling & s){
327  s.toStream(ostr);
328  return ostr;
329 }
330 
331 } // drain::
332 
333 #endif
334 
335 // Drain
tuplebase_t & assignSequence(T &sequence, bool LENIENT=false)
Proposed for tuples only; derived classes should not shadow this.
Definition: TupleBase.h:244
Tuple of N elements of type T.
Definition: UniTuple.h:65
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
void setPhysicalRange(double min, double max)
Sets the supported range for physical values. Does not change scaling or type.
Definition: ValueScaling.h:246
double getMinPhys() const
Returns the minimum physical value.
Definition: ValueScaling.h:269
drain::Range< double > physRange
Minimum and maximum physical value of the imaged quantity (not limited to corresponding to minCodeVal...
Definition: ValueScaling.h:74
bool isPhysical() const
Returns true, physical intensity range has been set.
Definition: ValueScaling.h:281
Range< double > & getPhysicalRange()
Returns a typical or supported range for physical values. Modifying the range will not change scaling...
Definition: ValueScaling.h:227
bool isScaled() const
Returns true, if scaling has effect ie. scale!=1.0 or offset!=0.0.
Definition: ValueScaling.h:263
void setAbsoluteScale()
If the intensities of the image correspond to an absolute value (like count) then the scale should be...
Definition: ValueScaling.h:161
double fwd(double x) const
Forward scaling: given encoded value x, returns corresponding value (possibly physically meaningful).
Definition: ValueScaling.h:295
virtual ValueScaling & getScaling()
Get linear scaling.
Definition: ValueScaling.h:153
virtual const ValueScaling & getScaling() const
Get linear scaling.
Definition: ValueScaling.h:147
double & offset
Additive coefficient \i b in: y = ax + b.
Definition: ValueScaling.h:71
void setPhysicalRange(const Range< T > &range)
Sets the supported range for physical values. Does not change scaling or type.
Definition: ValueScaling.h:240
double getOffset() const
Returns the intensity scaling offset, ie. b in a*x + b . See set setScale()
Definition: ValueScaling.h:256
void setConversionScale(double scale, double offset=0.0, double scaleOut=1.0, double offsetOut=0.0)
If the intensities of the image correspond to a physical value (like temperature),...
Definition: ValueScaling.h:182
void setPhysicalMax(double max)
In integer-valued images, set the physical values corresponding to [0, maxCodeValue].
Definition: ValueScaling.h:233
double getMaxPhys() const
Returns the maximum physical value.
Definition: ValueScaling.h:275
void setNormalScale(const std::type_info &t)
For "small integer" types, resets offset and scale such that maximum code value corresponds to 1....
Definition: ValueScaling.h:173
void setConversionScale(const drain::ValueScaling &s1, const drain::ValueScaling &s2)
Set scaling for which scaling.inv(x) = s2.inv(s1.fwd(x))
Definition: ValueScaling.h:188
const Range< double > & getPhysicalRange() const
Returns a typical or supported range for physical values.
Definition: ValueScaling.h:221
void adoptScaling(const drain::ValueScaling &srcScaling, const std::type_info &srcType, const std::type_info &dstType=typeid(void))
Sets scale and offset according to physical range and current type.
Definition: ValueScaling.cpp:73
virtual void setScaling(double scale, double offset)
Set linear scaling.
Definition: ValueScaling.h:136
void setPhysicalScale(const std::type_info &t, const drain::ValueScaling &scaling)
Sets physical range (min, max) and scales storage type accordingly.
Definition: ValueScaling.h:214
double inv(double y) const
Inverse scaling: given physically meaningful value y, returns the corresponding code value.
Definition: ValueScaling.h:301
void setOptimalScale(const std::type_info &t)
If storage type is integer, adjust scale such that resolution is maximized.
Definition: ValueScaling.cpp:36
void setPhysicalScale(const std::type_info &t, double min, double max)
Sets physical range (min, max) and scales storage type accordingly.
Definition: ValueScaling.h:204
double getScale() const
Returns the intensity scaling factor. See set setScale()
Definition: ValueScaling.h:252
Definition: DataSelector.cpp:1277