Loading...
Searching...
No Matches
DopplerWindowOp.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32
33#ifndef DOPPLER_WIN_OP_H_
34#define DOPPLER_WIN_OP_H_
35
36//#include "PolarSlidingWindowOp.h"
37
38#include <drain/Log.h>
39#include <drain/Type.h>
40#include <drain/TypeUtils.h>
41#include "data/Data.h"
42#include "data/DataSelector.h"
43#include "data/PolarODIM.h"
44#include "data/QuantityMap.h"
45//#include <drain/imageops/SlidingWindowHistogramOp.h>
46//#include <drain/imageops/SlidingWindowOp.h>
47//#include <drain/util/Fuzzy.h>
48//#include <drain/util/LookUp.h>
49#include <drain/image/Geometry.h>
50#include <drain/image/Image.h>
51#include <drain/image/ImageChannel.h>
52#include <drain/image/Window.h>
53#include <drain/imageops/SlidingWindowOp.h>
54#include "radar/Doppler.h"
55#include <drain/util/Fuzzy.h>
56#include <drain/util/SmartMap.h>
57#include <product/RadarProductOp.h>
58#include "DopplerOp.h"
59//#include <cmath>
60#include <string>
61
62
63namespace rack {
64
65
66
68
71template <class W>
72class DopplerWindowOp : public DopplerOp {
73
74public:
75
76
77 typename W::conf_t conf;
78
79
80
81
82 virtual ~DopplerWindowOp(){};
83
84
85 // Outputs uField and vField both, so dst dataSET needed
86 virtual
87 void processDataSet(const DataSet<PolarSrc> & srcSweep, DataSet<PolarDst> & dstProduct) const ;
88 // virtual void processImage(const PolarODIM & odim, const Image &src, Image &dst) const;
89
90 virtual
91 void processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const;
92
93protected:
94
99 DopplerWindowOp(const std::string & name, const std::string & description, int widthM, double heightD) :
100 DopplerOp(name, description), conf() { //, threshold(0.5), compensatePolar(true), relativeScale(relativeScale) {
101
102 parameters.link("width", this->conf.widthM = widthM, "metres");
103 parameters.link("height", this->conf.heightD = heightD, "deg");
104 //parameters.append(conf, false); // TODO: Window::conf parameters ?
105 parameters.link("threshold", this->conf.contributionThreshold = 0.5, "percentage");
106 parameters.link("compensate", this->conf.invertPolar = false, "cart/polar[0|1]");
107 //parameters.link("relativeScale", this->conf.relativeScale = false, "0|1");
108
109
110 dataSelector.setMaxCount(1);
112 allowedEncoding.link("type", odim.type);
113 allowedEncoding.link("gain", odim.scaling.scale);
114
115 };
116
117 virtual
118 void setEncoding(const ODIM & inputODIM, PlainData<PolarDst> & dst) const;
119
120
121 virtual
122 double getTypicalMin(const PolarODIM & srcODIM) const = 0;
123
124 virtual
125 double getTypicalMax(const PolarODIM & srcODIM) const = 0;
126
128 /*
129 void setPixelConf(typename W::conf_t & pixelConf, const PolarODIM & inputODIM) const {
130 this->conf.setPixelConf(pixelConf, inputODIM);
131 }
132 */
133
134};
135
136
137
138template <class W>
139void DopplerWindowOp<W>::setEncoding(const ODIM & inputODIM, PlainData<PolarDst> & dst) const {
140
141 drain::Logger mout(__FILE__, __FUNCTION__);
142
143 dst.odim.quantity = odim.quantity;
144
145 drain::ReferenceMap typeRef;
146 typeRef.link("type", dst.odim.type = odim.type);
147 typeRef.updateValues(targetEncoding);
148 dst.data.setType(dst.odim.type);
149
150 if (odim.scaling.scale != 0.0){ // NOTE: now dst.odim.scaling.scale at least default (1.0)
151 mout.warn("Init with ODIM: " , EncodingODIM(odim) );
152 //ProductOp::
153 applyODIM(dst.odim, odim);
154 }
155 else {
156 // const double max = (this->conf.relativeScale) ? 1.0 : inputODIM.NI;
157 if (drain::Type::call<drain::typeIsSmallInt>(dst.data.getType())){
158 dst.setPhysicalRange(getTypicalMin(inputODIM), getTypicalMax(inputODIM));
159 //mout.note(EncodingODIM(inputODIM) );
160 mout.debug("small int: " , EncodingODIM(dst.odim) );
161 mout.debug2("small int: " , dst.data );
162 // dstData.data.setScaling(dstData.odim.scaling.scale, dstData.odim.scaling.offset);
163 }
164 else {
165 if (drain::Type::call<drain::typeIsInteger>(dst.data.getType()))
166 mout.warn("large int" );
167 }
168 dst.odim.distinguishNodata(); // change undetect
169 }
170
171 //ProductBase::applyODIM(dst.odim, inputODIM, true); // New. Use defaults if still unset
172 ProductBase::completeEncoding(dst.odim, targetEncoding);
173
174 dst.data.setScaling(dst.odim.scaling); // needed?
175 //dst.data.setScaling(dst.odim.scaling.scale, dst.odim.scaling.offset);
176 mout.debug("final dst: " , dst.data );
177}
178
179
180template <class W>
181void DopplerWindowOp<W>::processDataSet(const DataSet<PolarSrc> & srcSweep, DataSet<PolarDst> & dstProduct) const {
182
183 drain::Logger mout(__FILE__, __FUNCTION__);
184
185 //const drain::RegExp quantityRe(dataSelector.getQuantity()); // "VRADH?";
186
187 const Data<PolarSrc> & vradSrc = srcSweep.getData(dataSelector.getQuantitySelector()); // (quantityRe); // consider data selector?
188
189 if (vradSrc.data.isEmpty()){
190 mout.warn("VRAD missing" );
191 return;
192 }
193
194 if (vradSrc.odim.getNyquist() == 0) {
195 mout.warn("VRAD unusable, vradSrc.odim.getNyquist() == 0" );
196 return;
197 }
198
199 Data<PolarDst> & dstData = dstProduct.getData(odim.quantity); // quality data?
200
201 dstData.odim.updateLenient(vradSrc.odim);
202 //dstData.odim.NI = vradSrc.odim.NI;
203 initDst(vradSrc.odim, dstData);
204
205 dstData.data.fill(dstData.odim.undetect); // NEW 2019/11
206
207 processData(vradSrc, dstData);
208 //mout.warn("after:" , dstData.data.getScaling() );
209
210
211 //@ dstProduct.updateTree(dstData.odim);
212
213
214}
215
216/*
217template <class W>
218void DopplerWindowOp<W>::setPixelConf(typename W::conf_t & pixelConf, const PolarODIM & inputODIM) const {
219
220 drain::Logger mout(__FILE__, __FUNCTION__);
221
222 // pixelConf = this->conf; PROBLEM: ftor prevents op=
223 pixelConf.widthM = this->conf.widthM;
224 pixelConf.heightD = this->conf.heightD;
225 pixelConf.updatePixelSize(inputODIM);
226 pixelConf.invertPolar = this->conf.invertPolar;
227 pixelConf.contributionThreshold = this->conf.contributionThreshold;
228 pixelConf.relativeScale = this->conf.relativeScale;
229
230 if (pixelConf.frame.width == 0){
231 mout.note(this->conf.frame.width );
232 mout.note(this->conf.widthM );
233 mout.note(*this );
234 mout.warn("Requested width (" , pixelConf.widthM , " meters) smaller than rscale (", inputODIM.rscale ,"), setting window width=1 " );
235 pixelConf.frame.width = 1;
236 }
237
238 if (pixelConf.frame.height == 0){
239 mout.warn("Requested height (" , pixelConf.heightD , " degrees) smaller than 360/nrays (", (360.0/inputODIM.geometry.height) ,"), setting window height=1 " );
240 pixelConf.frame.height = 1;
241 }
242
243}
244*/
245
246// NOTE: window.write() may skip ftor! ?
247template <class W>
248void DopplerWindowOp<W>::processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const {
249
250 drain::Logger mout(__FILE__, __FUNCTION__);
251
252 //DopplerDevWindow w;
253 //w.initialize();
254
255 typename W::conf_t pixelConf;
256 this->conf.setPixelConf(pixelConf, vradSrc.odim);
257 //setPixelConf(pixelConf, vradSrc.odim);
258
259 SlidingWindowOp<W> op(pixelConf);
260 mout.debug(op );
261 mout.special("provided functor: " , op.conf.getFunctorName() , '|' , op.conf.functorParameters );
262 mout.debug("pixelConf.contributionThreshold " , pixelConf.contributionThreshold );
263 mout.debug("op.conf.contributionThreshold " , op.conf.contributionThreshold );
264 //dstData.data.setGeometry(vradSrc.data.getGeometry()); // setDst() handles
265 //op.process(vradSrc.data, dstData.data);
266 //op.traverseChannel(vradSrc.data.getChannel(0), dstData.data.getChannel(0));
267 op.traverseChannel(vradSrc.data, dstData.data);
268
269 dstData.odim.prodpar = this->parameters.getValues();
270 //@~ dstData.updateTree();
271
272}
273
275/*
276class DopplerAvgOp : public DopplerWindowOp<DopplerAverageWindow> {
277public:
278
279 **
280 * \param width - radial extent of window, in metres
281 * \param height - azimuthal extent of window, in degrees
282 *
283 DopplerAvgOp(int width = 1500, double height = 3.0) :
284 DopplerWindowOp<DopplerAverageWindow>(__FUNCTION__, "Smoothens Doppler field", width, height) {
285 parameters.link("relativeScale", this->conf.relativeScale = false, "0|1");
286 odim.quantity = "VRAD"; // VRAD_C (corrected)?
287 };
288
289 virtual ~DopplerAvgOp(){};
290
291protected:
292
293 virtual inline
294 double getTypicalMin(const PolarODIM & srcODIM) const {
295 return (this->conf.relativeScale) ? -1.0 : -srcODIM.getNyquist();
296 }
297
298 virtual inline
299 double getTypicalMax(const PolarODIM & srcODIM) const {
300 return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
301 }
302
303};
304*/
305
306class DopplerAvgOp : public DopplerWindowOp<DopplerAverageWindow2> {
307public:
308
313 DopplerAvgOp(int width = 1500, double height = 3.0) :
314 DopplerWindowOp<DopplerAverageWindow2>(__FUNCTION__, "Smoothens Doppler field, providing quality", width, height) {
315 parameters.link("relativeScale", this->conf.relativeScale = false, "false|true");
316 odim.quantity = "VRAD"; // VRAD_C (corrected)?
317 };
318
319 virtual ~DopplerAvgOp(){};
320
321 virtual inline
322 void processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const {
323
324 drain::Logger mout(__FILE__, __FUNCTION__);
325 drain::FuzzyBell2<double> deviationQuality(1.0, 0.125); // 50m/s
326 DopplerAverageWindow2::conf_t pixelConf(deviationQuality);
327 // setPixelConf(pixelConf, vradSrc.odim);
328 this->conf.setPixelConf(pixelConf, vradSrc.odim);
329
330 mout.debug("radarConf: " , this->conf.widthM , 'x' , this->conf.heightD );
331 mout.debug("pixelConf: " , pixelConf.frame.width , 'x' , this->conf.frame.height );
332
334 mout.debug(op );
335 mout.warn(op );
336 mout.special("provided functor: " , op.conf.getFunctorName() , '|' , op.conf.functorParameters );
337 //mout.debug("provided functor: " , op.conf.ftor );
338
339 const drain::image::Geometry & g = vradSrc.data.getGeometry();
340
341 drain::image::Image dummy(g.getWidth(), g.getHeight());
342
343 PlainData<PolarDst> & dstQuality = dstData.getQualityData("QIND");
344 getQuantityMap().setQuantityDefaults(dstQuality, "QIND");
345 dstQuality.setGeometry(g.getWidth(), g.getHeight());
346
347 op.traverseChannel(vradSrc.data, dummy, dstData.data, dstQuality.data);
348
349 dstData.odim.prodpar = this->parameters.getValues();
350 }
351
352protected:
353
354 virtual inline
355 double getTypicalMin(const PolarODIM & srcODIM) const {
356 return (this->conf.relativeScale) ? -1.0 : -srcODIM.getNyquist();
357 }
358
359 virtual inline
360 double getTypicalMax(const PolarODIM & srcODIM) const {
361 return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
362 }
363
364};
365
366
367
368class DopplerEccentricityOp : public DopplerWindowOp<DopplerEccentricityWindow> {
369public:
370
375 DopplerEccentricityOp(int widthM = 1500, double heightD = 3.0) :
376 DopplerWindowOp<DopplerEccentricityWindow>(__FUNCTION__, "Magnitude of mean unit circle mapped Doppler speeds", widthM, heightD) {
377
378 //parameters.link("relativeScale", this->conf.relativeScale = true, "true|false");
379
380 //this->conf.relativeScale = true;
381 odim.quantity = "VRAD_DEV"; // VRAD_C ?
382 odim.scaling.scale = 1.0/200.0;
383 odim.scaling.offset = -odim.scaling.scale;
384 //odim.scaling.scale = 1.0/200.0;
385 odim.type = "C";
386 odim.nodata = 255; // TODO
387 };
388
389 virtual ~DopplerEccentricityOp(){};
390
391protected:
392
393 virtual inline
394 double getTypicalMin(const PolarODIM & srcODIM) const {
395 return 0.0;
396 }
397
398 virtual inline
399 double getTypicalMax(const PolarODIM & srcODIM) const {
400 return +1.0;
401 //return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
402 }
403
404
405};
406
407
408
409
410}
411
412
413#endif /* DOPPLERDevOP_H_ */
A smooth symmetric peak function that resembles the Gaussian bell curve. Diminishes quicker than Fuzz...
Definition Fuzzy.h:432
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Definition ReferenceMap.h:207
virtual void clear()
Removes all the elements of the map.
Definition ReferenceMap.h:374
void getValues(std::ostream &ostr) const
Dumps the values.
Definition SmartMap.h:353
void updateValues(const std::string &entries, char assignmentSymbol='=', char separatorSymbol=0)
Sets applicable values ie. modifies existing entries only. In ordered maps, skips extra entries silen...
Definition SmartMap.h:326
Definition Geometry.h:145
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition Image.h:184
Template for operators applying pipeline-like sliding window.
Definition SlidingWindowOp.h:59
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition Data.h:1215
Data structure consisting of plain data and an optional quality data.
Definition Data.h:1146
Smoothens Doppler field, providing quality computed as eccentricity.
Definition Doppler.h:229
Simple op not producing quality field.
Definition DopplerWindowOp.h:306
DopplerAvgOp(int width=1500, double height=3.0)
Definition DopplerWindowOp.h:313
Definition DopplerWindowOp.h:368
DopplerEccentricityOp(int widthM=1500, double heightD=3.0)
Definition DopplerWindowOp.h:375
Computes eccentrity of Doppler speeds mapped on a Nyquist-normalized unit window.
Definition Doppler.h:314
Base class for computing products using Doppler speed [VRAD] data.
Definition DopplerOp.h:49
Base class for Doppler average and variance.
Definition DopplerWindowOp.h:72
DopplerWindowOp(const std::string &name, const std::string &description, int widthM, double heightD)
Definition DopplerWindowOp.h:99
ODIM metadata (quantity, gain, offset, undetect, nodata, date, time)
Definition ODIM.h:79
Essential class for storing radar data.
Definition Data.h:300
Metadata structure for single-radar data (polar scans, volumes and products).
Definition PolarODIM.h:45
drain::ReferenceMap allowedEncoding
Defines which encoding parameters can be changed by the user from command line.
Definition ProductBase.h:205
bool setQuantityDefaults(EncodingODIM &dst, const std::string &quantity, const std::string &values="") const
Sets default values of given quantity without assigning the quantity. Optionally overrides with user ...
Definition QuantityMap.cpp:207
MD odim
The default data parameters for encoding output (the product).
Definition RadarProductOp.h:101
Definition DataSelector.cpp:44
QuantityMap & getQuantityMap()
Definition QuantityMap.cpp:279