RadarWindows.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 RACK_RADAR_WINDOWS_H
32 #define RACK_RADAR_WINDOWS_H
33 
34 #include <math.h>
35 
36 #include <drain/Log.h>
37 #include <drain/TypeUtils.h>
38 #include <drain/util/Fuzzy.h>
39 #include <drain/util/Functor.h>
40 #include <drain/util/FunctorBank.h>
41 #include <drain/image/Window.h>
42 #include <drain/image/SegmentProber.h>
43 #include <drain/image/SlidingWindow.h>
44 #include <drain/image/GaussianWindow.h>
45 #include <drain/imageops/FunctorOp.h>
46 #include <drain/imageops/GaussianAverageOp.h>
47 //#include "drain/image/SequentialImageOp.h"
48 
49 #include "data/ODIM.h"
50 #include "data/PolarODIM.h"
51 #include "data/Quantity.h"
52 
53 using namespace drain::image;
54 
55 // file RadarFunctorOp?
56 
57 namespace rack {
58 
59 
61 
62 
63 public:
64 
66 
68  RadarWindowCore() : NI(0.0) {
69  }
70 
74  //RadarWindowCore(const PolarODIM & odimSrc) : odimSrc(odimSrc) {
75  //}
76 
77 
78  //const PolarODIM & odimSrc;
80 
81 
84  mutable double NI;
85 
86 };
87 
89 
93 class RadarWindowGeom : public drain::UniTuple<double,2> {
94 
95 public:
96 
97  RadarWindowGeom() : widthM(this->next()), heightD(this->next()) {
98  }
99 
100  RadarWindowGeom(const RadarWindowGeom & geom) : widthM(next()), heightD(next()) {
101  assignSequence(geom.tuple());
102  }
103 
104  // Beam-directional window width in metres
105  double & widthM; // = 1500.0;
106 
107  // Azimuthal window height in degrees
108  double & heightD; // = 3.0;
109 
110 };
111 
113 
114 public:
115 
117  double contributionThreshold = 0.5; //
118 
120  bool invertPolar = false;
121 
123  bool relativeScale = false; //
124 
130  RadarWindowConfig(int widthM=1500, double heightD=3.0, double contributionThreshold = 0.5, bool invertPolar=false, bool relativeScale=false) :
131  drain::image::WindowConfig(1, 1), // drain::image::WindowConfig(width, height),
132  // widthM(widthM), heightD(heightD),
133  contributionThreshold(contributionThreshold), invertPolar(invertPolar), relativeScale(relativeScale) {
134  this->widthM = widthM;
135  this->heightD = heightD;
136  }
137 
138  RadarWindowConfig(const RadarWindowConfig & conf) :
139  RadarWindowGeom(conf),
140  drain::image::WindowConfig(conf),
141  //widthM(conf.widthM),
142  //heightD(conf.heightD),
143  contributionThreshold(conf.contributionThreshold),
144  invertPolar(conf.invertPolar),
145  relativeScale(conf.relativeScale){
146 
147  }
148 
157  //RadarWindowConfig(drain::UnaryFunctor & ftor, int width=3, int height=3, double contributionThreshold = 0.5) :
158  template <class FT>
159  RadarWindowConfig(const FT & ftor, int widthM=1500, double heightD=3.0,
160  double contributionThreshold = 0.5, bool invertPolar=false, bool relativeScale=false) :
161  drain::image::WindowConfig(0, 0, ftor), //drain::image::WindowConfig(ftor, width, height),
162  //widthM(widthM), heightD(heightD),
163  contributionThreshold(contributionThreshold), invertPolar(invertPolar), relativeScale(relativeScale) {
164  // invertPolar(false), contributionThreshold(contributionThreshold) {
165  this->widthM = widthM;
166  this->heightD = heightD;
167  }
168 
169  // Perhaphs deprecating.
171  void setPixelConf(RadarWindowConfig & conf, const PolarODIM & inputODIM) const;
172 
173  // NEW, "Inverted" setPixelConf
175  void adjustMyConf(const RadarWindowConfig & conf, const PolarODIM & inputODIM);
176 
177 
178  void updatePixelSize(const PolarODIM & inputODIM);
179 
180 };
181 
182 
183 
185 
191 template <class C, class R=RadarWindowCore>
193 public:
194 
195  SlidingRadarWindowBase(int width=0, int height=0) : drain::image::SlidingWindow<C,R>(width,height), rangeNorm(1), rangeNormEnd(2), countMin(0) {
196  this->resetAtEdges = true;
197  };
198 
199  SlidingRadarWindowBase(const C & conf) : drain::image::SlidingWindow<C,R>(conf), rangeNorm(1), rangeNormEnd(2), countMin(0) {
200  this->resetAtEdges = conf.invertPolar;
201  //this->resetAtEdges = true; //conf.invertPolar;
202  };
203 
204  virtual
206 
208  // Redefines Window<C,R>::setSrcFrame(ImageFrame)
213 
214  drain::Logger mout("SlidingRadarWindow", __FUNCTION__);
215  //mout.debug("src Scaling0: " , src.getScaling() );
216  mout.debug2("src props for odim: " , src.getProperties() );
217 
218  this->odimSrc.updateFromMap(src.getProperties());
219  mout.info("NI=" , this->odimSrc.getNyquist(LOG_WARNING) );
220  mout.info("copied odim: " , EncodingODIM(this->odimSrc) );
221 
223  // direct should be:
224  // R::setSrcFrame(src);
225  mout.debug2("src Scaling: " , src.getScaling() );
226  }
227 
228  /*
229  void setDst(drain::image::ImageFrame & dst){
230  drain::Logger mout("SlidingRadarWindow", __FUNCTION__);
231  //this->odimSrc.updateFromMap(src.getProperties());
232  //mout.debug("copied odim: " , this->odimSrc );
233  SlidingWindow<C, RadarWindowCore>::setDst(dst);
234  }
235  */
236 
237 protected:
238 
239  virtual
240  void initialize() override {
241  setImageLimits();
242  setRangeNorm(); // interplay setLoopLimits(), with reset() and
243  //if (drain::Type::call<drain::typeIsSmallInt>(this->src.getType()) && drain::Type::call<drain::drain::typeIsSmallInt>(this->dst.getType())){
244  if (drain::Type::call<drain::typeIsSmallInt>(this->dst.getType())){
245  drain::Logger mout("SlidingRadarWindow", __FUNCTION__);
246  //this->conf.ftor.setScale(1.0);
247  mout.info("(not implemented: functor scaling for small int dst)" ); // << this->odimSrc
248  }
249  // what about reset(); ?
250  reset();
251  };
252 
253 
254  inline
255  void setImageLimits() const {
256  this->coordinateHandler.set(this->src.getGeometry(), this->src.getCoordinatePolicy());
257  // this->src.adjustCoordinateHandler(this->coordinateHandler);
258  }
259 
261  void setRangeNorm(){
262 
263  drain::Logger mout("SlidingRadarWindow", __FUNCTION__);
264 
265  if (this->odimSrc.area.height == 0)
266  mout.error("src odim.area.height==0" );
267 
269  const double r = static_cast<double>(this->odimSrc.area.height) / (2.0*M_PI);
270  const int max = static_cast<int>(this->odimSrc.area.width);
271 
272  rangeNorm = static_cast<int>(r);
274  rangeNormEnd = static_cast<int>(r * static_cast<double>(this->conf.frame.height));
275  if ((rangeNorm <= 0) || (rangeNormEnd >= max)){
276  mout.note(rangeNorm , '-' , rangeNormEnd );
277  }
278  //
279  }
280 
281  int rangeNorm;
282  int rangeNormEnd;
283  int countMin; // raise
284 
285 
287  virtual inline
288  bool reset(){
289 
290  if (this->location.x <= rangeNorm){
291  this->setLoopLimits(this->conf.frame.width, this->conf.frame.height);
292  }
293  else if (this->location.x < rangeNormEnd){ // from 'height' down to 1
294  this->setLoopLimits(this->conf.frame.width, (rangeNorm * this->conf.frame.height)/(this->location.x+1) );
295  //std::cerr << "loop limits " << this->jMax << std::endl;
296  }
297  else {
298  this->setLoopLimits(this->conf.frame.width, 1);
299  }
300  //drain::Logger mout("SlidingRadarWindow", __FUNCTION__);
301  //mout.warn(this->iMax , ',' , this->jMax , '\t' , this->getSamplingArea( ));
302  countMin = this->conf.contributionThreshold * this->getSamplingArea();
303 
304  return SlidingWindow<C,R>::reset();
305  };
306 
307 };
308 
309 
310 template <class C, class R=RadarWindowCore>
311 class SlidingRadarWindow : public SlidingRadarWindowBase<C,R> { // drain::image::WeightedWindowCore
312 public:
313 
314  inline
315  SlidingRadarWindow(int width=0, int height=0) : SlidingRadarWindowBase<C,R>(width, height) {
316  };
317 
318  inline
319  SlidingRadarWindow(const C & conf) : SlidingRadarWindowBase<C,R>(conf) {
320  };
321 
322 
323  virtual inline
325  if (this->coordinateHandler.validate(p)){
326  double x = this->src.template get<double>(p);
327  if ((x != this->odimSrc.nodata) && (x != this->odimSrc.undetect))
328  removeTrailingValue(this->odimSrc.scaleForward(x));
329  }
330  };
331 
332  virtual inline
334  if (this->coordinateHandler.validate(p)){
335  double x = this->src.template get<double>(p);
336  if ((x != this->odimSrc.nodata) && (x != this->odimSrc.undetect))
337  addLeadingValue(this->odimSrc.scaleForward(x));
338  }
339  };
340 
342  virtual inline
343  void removeTrailingValue(double x){}; // = 0;
344 
346  virtual inline
347  void addLeadingValue(double x){}; // = 0;
348 
349 
350 
351 };
352 
357 template <class C>
359 public:
360 
361  //drain::UnaryFunctor & myFunctor;
362 
363  RadarWindowAvg(int width=0, int height=0) :
364  SlidingRadarWindow<C>(width,height),
365  //myFunctor(this->conf.getFunctor()),
366  sum(0.0),
367  count(0) {
368  };
369 
370  RadarWindowAvg(const RadarWindowAvg & window) :
371  SlidingRadarWindow<C>(window),
372  //myFunctor(this->conf.getFunctor(window.conf.getFunctorName())), // kludge
373  sum(0.0),
374  count(0) {
375  };
376 
377  RadarWindowAvg(const C & conf) :
378  SlidingRadarWindow<C>(conf),
379  // myFunctor(this->conf.getFunctor(conf.getFunctorName())),
380  sum(0.0),
381  count(0) {
382  };
383 
384 
385 
386 
387  virtual
388  inline
389  ~RadarWindowAvg(){};
390 
392 
393 protected:
394 
395  double sum;
396  int count;
397 
398  virtual
399  inline
400  void clear(){
401  sum = 0.0;
402  count = 0;
403  };
404 
405  virtual inline
406  void removeTrailingValue(double x){
407  sum -= x;
408  --count;
409  };
410 
411  virtual inline
412  void addLeadingValue(double x){
413  sum += x;
414  ++count;
415  };
416 
417  virtual inline
418  void write(){
419  if (count > 0){
420  //if (this->location.x == this->location.y)
421  // std::cerr << sum << '\t' << count << '\n';
422  this->dst.putScaled(this->location.x, this->location.y, this->myFunctor(sum/static_cast<double>(count)));
423  }
424  else
425  this->dst.put(this->location, this->odimSrc.undetect); // ?
426  };
427 
428 
429 };
430 
435 template <class C>
437 public:
438 
439 
440  // Consider metres & degrees?
441  RadarWindowWeightedAvg(int width=0, int height=0) : SlidingRadarWindow<C>(width,height) {
442  };
443 
445  };
446 
447  RadarWindowWeightedAvg(const C & conf) : SlidingRadarWindow<C>(conf) {
448  };
449 
450  virtual inline
452 
453 protected:
454 
455  int count = 0;
456 
457  // Copied from SlidingStripeAverage
458  typedef float sum_t;
459  sum_t w = 0.0;
460  sum_t sum = 0.0;
461  sum_t sumW = 0.0;
462 
463  virtual inline
464  void clear() final {
465  this->sum = 0.0;
466  this->sumW = 0.0;
467  this->count = 0;
468  };
469 
470 
471  virtual inline
472  void addPixel(drain::Point2D<int> & p) final {
473  if (this->coordinateHandler.validate(p)){
474  double x = this->src.template get<double>(p);
475  if (this->odimSrc.isValue(x)){
476  this->w = this->srcWeight.template get<sum_t>(p);
477  this->sum += w*this->odimSrc.scaling.fwd(x);
478  this->sumW += w;
479  ++this->count;
480  }
481  }
482  };
483 
484  virtual inline
486  if (this->coordinateHandler.validate(p)){
487  double x = this->src.template get<double>(p);
488  if (this->odimSrc.isValue(x)){
489  this->w = this->srcWeight.template get<sum_t>(p);
490  this->sum -= w*this->odimSrc.scaling.fwd(x);
491  this->sumW -= w;
492  --this->count;
493  }
494  }
495  };
496 
497  virtual inline
498  void write() final {
499  if (sumW > 0.0){ // then also count>0
500  this->dst.put(this->location, this->odimSrc.scaling.inv(this->sum/sumW));
501  //this->dstWeight.put(this->location, this->scalingW.inv(sumW/static_cast<sum_t>(this->count)));
502  this->dstWeight.put(this->location, sumW/static_cast<sum_t>(this->count)); // "uses" original scaling
503  }
504  else {
505  this->dst.put(this->location, this->odimSrc.undetect); // change
506  this->dstWeight.put(this->location, 0);
507  }
508 
509  }
510 
511  /*
512  virtual inline
513  void removeTrailingValue(double x) final {
514  sum -= x;
515  --count;
516  };
517 
518  virtual inline
519  void addLeadingValue(double x) final {
520  sum += x;
521  ++count;
522  };
523 
524  virtual inline
525  void write(){
526  if (count > 0){
527  //if (this->location.x == this->location.y)
528  // std::cerr << sum << '\t' << count << '\n';
529  this->dst.putScaled(this->location.x, this->location.y, this->myFunctor(sum/static_cast<double>(count)));
530  }
531  else
532  this->dst.put(this->location, this->odimSrc.undetect); // ?
533  };
534  */
535 
536 
537 };
538 
539 
543 template <class C>
545 public:
546 
547  RadarWindowSoftMax(int width=0, int height=0, double coeff=1.0) : SlidingRadarWindow<C>(width,height), coeff(1.0), coeffInv(1.0/coeff), sum(0.0), count(0) {};
548 
549 
550  virtual inline
551  ~RadarWindowSoftMax(){};
552 
553  void setCoeff(double c){
554  if (c==0.0)
555  throw std::runtime_error("RadarWindowSoftMax: zero coeff");
556  coeff = c;
557  coeffInv = 1.0/c;
558  };
559 
560 protected:
561 
562  double coeff;
563  double coeffInv;
564 
565  double sum;
566  int count;
567 
568  virtual inline
569  void clear(){
570  sum = 0.0;
571  count = 0;
572  };
573 
574  virtual inline
575  void removeTrailingValue(double x){
576  sum -= ::exp(coeff * x);
577  --count;
578  };
579 
580  virtual inline
581  void addLeadingValue(double x){
582  sum += ::exp(coeff * x);
583  ++count;
584  //if ((p.x == p.y) && (x > -15.0))
585  // std::cerr << "handleLeadingPixel" << p << ':' << x << '\t' << count << ':' << sum << std::endl;
586  };
587 
588  virtual inline
589  void write(){
590  if (count > 0)
591  this->dst.put(this->location, this->fuzzifier(coeffInv*::log(sum/static_cast<double>(count))));
592  //this->dst.put(this->location, this->functor(sum/static_cast<double>(count)));
593  };
594 
595 
596 };
597 
599 
604 template <class F>
606 public:
607 
608  RadarWindowStdDev(int width=0, int height=0) : SlidingRadarWindow<F>(width,height), sum(0.0), sum2(0.0), count(0) {};
609 
610 
611  virtual inline
612  ~RadarWindowStdDev(){};
613 
614 protected:
615 
616  double sum;
617  double sum2;
618  int count;
619 
620  virtual inline
621  void clear(){
622  sum = 0.0;
623  sum2 = 0.0;
624  count = 0;
625  };
626 
627  virtual
628  inline
629  void removeTrailingValue(double x){
630  sum -= x;
631  sum2 -= x*x;
632  --count;
633  };
634 
635  virtual
636  inline
637  void addLeadingValue(double x){
638  sum += x;
639  sum2 += x*x;
640  ++count;
641  //if ((this->p.x == this->p.y) && (x > -15.0))
642  // std::cerr << "handleLeadingPixel" << this->p << ':' << x << '\t' << count << ':' << sum << std::endl;
643  };
644 
645  virtual
646  inline
647  void write(){
648 
649  if (count > 0){
650  double countD = static_cast<double>(count);
651  this->dst.put(this->location, this->fuzzifier( ::sqrt(sum2/countD - sum*sum/(countD*countD)) ));
652  /*
653  countD = sum2/countD - sum*sum/(countD*countD);
654  if ((this->p.x == this->p.y) && (count > 5))
655  std::cerr << __FUNCTION__ << this->p << ':' << countD << std::endl;
656  */
657  }
658  else
659  this->dst.put(this->location, 0);
660 
661  };
662 
663 
664 };
665 
666 
667 
668 
669 
670 
671 
672 } // rack::
673 
674 
675 
676 
677 #endif
678 
679 // Rack
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:412
Logger & note(const TT &... args)
For top-level information.
Definition: Log.h:485
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
Tuple of N elements of type T.
Definition: UniTuple.h:65
Image with static geometry.
Definition: ImageFrame.h:67
Window implementation that uses incremental update of state.
Definition: SlidingWindow.h:50
virtual bool reset()
Returns false, if traversal should be ended.
Definition: SlidingWindow.h:212
Definition: Window.h:268
Base class for configurations applied in image processing windows, e.g. for operators of type WindowO...
Definition: Window.h:56
Structure for data storage type, scaling and marker codes. Does not contain quantity.
Definition: EncodingODIM.h:75
Metadata structure for single-radar data (polar scans, volumes and products).
Definition: PolarODIM.h:45
Definition: RadarWindows.h:358
virtual void write()
Write the result in the target image.
Definition: RadarWindows.h:418
virtual void removeTrailingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:406
virtual void addLeadingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:412
virtual void clear()
Clears the applied statistics. Redefined in derived classes.
Definition: RadarWindows.h:400
Definition: RadarWindows.h:112
RadarWindowConfig(int widthM=1500, double heightD=3.0, double contributionThreshold=0.5, bool invertPolar=false, bool relativeScale=false)
Definition: RadarWindows.h:130
RadarWindowConfig(const FT &ftor, int widthM=1500, double heightD=3.0, double contributionThreshold=0.5, bool invertPolar=false, bool relativeScale=false)
Definition: RadarWindows.h:159
Definition: RadarWindows.h:60
PolarODIM odimSrc
Definition: RadarWindows.h:79
double NI
Definition: RadarWindows.h:84
RadarWindowCore()
Will act as base class: Window<RadarWindowCore> : public RadarWindowCore {...}, init currently not su...
Definition: RadarWindows.h:68
Like pixel window, but width is metres and height is degrees.
Definition: RadarWindows.h:93
Definition: RadarWindows.h:544
virtual void write()
Write the result in the target image.
Definition: RadarWindows.h:589
virtual void removeTrailingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:575
virtual void addLeadingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:581
virtual void clear()
Clears the applied statistics. Redefined in derived classes.
Definition: RadarWindows.h:569
Sliding window for computing standard deviation of scalar quantities.
Definition: RadarWindows.h:605
virtual void write()
Write the result in the target image.
Definition: RadarWindows.h:647
virtual void removeTrailingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:629
virtual void addLeadingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:637
virtual void clear()
Clears the applied statistics. Redefined in derived classes.
Definition: RadarWindows.h:621
Definition: RadarWindows.h:436
virtual void addPixel(drain::Point2D< int > &p) final
Adds a pixel to window statistics. Unvalidated location.
Definition: RadarWindows.h:472
virtual void removePixel(drain::Point2D< int > &p) final
Removes a pixel from window statistics. Unvalidated location.
Definition: RadarWindows.h:485
virtual void write() final
Write the result in the target image.
Definition: RadarWindows.h:498
virtual void clear() final
Clears the applied statistics. Redefined in derived classes.
Definition: RadarWindows.h:464
A two-dimensional image processing window that handles the special ODIM codes and scales the result....
Definition: RadarWindows.h:192
void setImageLimits() const
Sets internal limits corresponding to image geometries. Typically using coordHandler.
Definition: RadarWindows.h:255
void setSrcFrame(const drain::image::ImageFrame &src)
Sets input image and retrieves ODIM metadata from image Properties.
Definition: RadarWindows.h:212
virtual void initialize() override
Sets class-specific initial values. Does not change general window state (e.g. location)....
Definition: RadarWindows.h:240
virtual bool reset()
Returns false, if traversal should be ended.
Definition: RadarWindows.h:288
void setRangeNorm()
To compensate polar geometry, set applicable range for pixel area scaling.
Definition: RadarWindows.h:261
Definition: RadarWindows.h:311
virtual void addPixel(drain::Point2D< int > &p)
Adds a pixel to window statistics. Unvalidated location.
Definition: RadarWindows.h:333
virtual void removePixel(drain::Point2D< int > &p)
Removes a pixel from window statistics. Unvalidated location.
Definition: RadarWindows.h:324
virtual void removeTrailingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:343
virtual void addLeadingValue(double x)
Handles the converted (natural-scaled) value.
Definition: RadarWindows.h:347
Namespace for images and image processing tools.
Definition: AccumulationArray.cpp:45
Definition: DataSelector.cpp:1277
Definition: DataSelector.cpp:44