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/Window.h>
52#include <drain/imageops/SlidingWindowOp.h>
53#include "radar/Doppler.h"
54#include <drain/util/Fuzzy.h>
55#include "DopplerOp.h"
56//#include <cmath>
57#include <string>
58
59
60namespace rack {
61
62
63
65
68template <class W>
69class DopplerWindowOp : public DopplerOp {
70
71public:
72
73
74 typename W::conf_t conf;
75
76
77
78
79 virtual ~DopplerWindowOp(){};
80
81
82 // Outputs uField and vField both, so dst dataSET needed
83 virtual
84 void processDataSet(const DataSet<PolarSrc> & srcSweep, DataSet<PolarDst> & dstProduct) const ;
85 // virtual void processImage(const PolarODIM & odim, const Image &src, Image &dst) const;
86
87 virtual
88 void processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const;
89
90protected:
91
96 DopplerWindowOp(const std::string & name, const std::string & description, int widthM, double heightD) :
97 DopplerOp(name, description), conf() { //, threshold(0.5), compensatePolar(true), relativeScale(relativeScale) {
98
99 parameters.link("width", this->conf.widthM = widthM, "metres");
100 parameters.link("height", this->conf.heightD = heightD, "deg");
101 //parameters.append(conf, false); // TODO: Window::conf parameters ?
102 parameters.link("threshold", this->conf.contributionThreshold = 0.5, "percentage");
103 parameters.link("compensate", this->conf.invertPolar = false, "cart/polar[0|1]");
104 //parameters.link("relativeScale", this->conf.relativeScale = false, "0|1");
105
106
107 dataSelector.setMaxCount(1);
109 allowedEncoding.link("type", odim.type);
110 allowedEncoding.link("gain", odim.scaling.scale);
111
112 };
113
114 virtual
115 void setEncoding(const ODIM & inputODIM, PlainData<PolarDst> & dst) const;
116
117
118 virtual
119 double getTypicalMin(const PolarODIM & srcODIM) const = 0;
120
121 virtual
122 double getTypicalMax(const PolarODIM & srcODIM) const = 0;
123
125 /*
126 void setPixelConf(typename W::conf_t & pixelConf, const PolarODIM & inputODIM) const {
127 this->conf.setPixelConf(pixelConf, inputODIM);
128 }
129 */
130
131};
132
133
134
135template <class W>
136void DopplerWindowOp<W>::setEncoding(const ODIM & inputODIM, PlainData<PolarDst> & dst) const {
137
138 drain::Logger mout(__FILE__, __FUNCTION__);
139
140 dst.odim.quantity = odim.quantity;
141
142 drain::ReferenceMap typeRef;
143 typeRef.link("type", dst.odim.type = odim.type);
144 typeRef.updateValues(targetEncoding);
145 dst.data.setType(dst.odim.type);
146
147 if (odim.scaling.scale != 0.0){ // NOTE: now dst.odim.scaling.scale at least default (1.0)
148 mout.warn("Init with ODIM: " , EncodingODIM(odim) );
149 //ProductOp::
150 applyODIM(dst.odim, odim);
151 }
152 else {
153 // const double max = (this->conf.relativeScale) ? 1.0 : inputODIM.NI;
154 if (drain::Type::call<drain::typeIsSmallInt>(dst.data.getType())){
155 dst.setPhysicalRange(getTypicalMin(inputODIM), getTypicalMax(inputODIM));
156 //mout.note(EncodingODIM(inputODIM) );
157 mout.debug("small int: " , EncodingODIM(dst.odim) );
158 mout.debug2("small int: " , dst.data );
159 // dstData.data.setScaling(dstData.odim.scaling.scale, dstData.odim.scaling.offset);
160 }
161 else {
162 if (drain::Type::call<drain::typeIsInteger>(dst.data.getType()))
163 mout.warn("large int" );
164 }
165 dst.odim.distinguishNodata(); // change undetect
166 }
167
168 //ProductBase::applyODIM(dst.odim, inputODIM, true); // New. Use defaults if still unset
169 dst.odim.completeEncoding( targetEncoding);
170
171 dst.data.setScaling(dst.odim.scaling); // needed?
172 //dst.data.setScaling(dst.odim.scaling.scale, dst.odim.scaling.offset);
173 mout.debug("final dst: " , dst.data );
174}
175
176
177template <class W>
178void DopplerWindowOp<W>::processDataSet(const DataSet<PolarSrc> & srcSweep, DataSet<PolarDst> & dstProduct) const {
179
180 drain::Logger mout(__FILE__, __FUNCTION__);
181
182 //const drain::RegExp quantityRe(dataSelector.getQuantity()); // "VRADH?";
183
184 const Data<PolarSrc> & vradSrc = srcSweep.getData(dataSelector.getQuantitySelector()); // (quantityRe); // consider data selector?
185
186 if (vradSrc.data.isEmpty()){
187 mout.warn("VRAD missing" );
188 return;
189 }
190
191 if (vradSrc.odim.getNyquist() == 0) {
192 mout.warn("VRAD unusable, vradSrc.odim.getNyquist() == 0" );
193 return;
194 }
195
196 Data<PolarDst> & dstData = dstProduct.getData(odim.quantity); // quality data?
197
198 dstData.odim.updateLenient(vradSrc.odim);
199 //dstData.odim.NI = vradSrc.odim.NI;
200 initDst(vradSrc.odim, dstData);
201
202 dstData.data.fill(dstData.odim.undetect); // NEW 2019/11
203
204 processData(vradSrc, dstData);
205 //mout.warn("after:" , dstData.data.getScaling() );
206
207
208 //@ dstProduct.updateTree(dstData.odim);
209
210
211}
212
213/*
214template <class W>
215void DopplerWindowOp<W>::setPixelConf(typename W::conf_t & pixelConf, const PolarODIM & inputODIM) const {
216
217 drain::Logger mout(__FILE__, __FUNCTION__);
218
219 // pixelConf = this->conf; PROBLEM: ftor prevents op=
220 pixelConf.widthM = this->conf.widthM;
221 pixelConf.heightD = this->conf.heightD;
222 pixelConf.updatePixelSize(inputODIM);
223 pixelConf.invertPolar = this->conf.invertPolar;
224 pixelConf.contributionThreshold = this->conf.contributionThreshold;
225 pixelConf.relativeScale = this->conf.relativeScale;
226
227 if (pixelConf.frame.width == 0){
228 mout.note(this->conf.frame.width );
229 mout.note(this->conf.widthM );
230 mout.note(*this );
231 mout.warn("Requested width (" , pixelConf.widthM , " meters) smaller than rscale (", inputODIM.rscale ,"), setting window width=1 " );
232 pixelConf.frame.width = 1;
233 }
234
235 if (pixelConf.frame.height == 0){
236 mout.warn("Requested height (" , pixelConf.heightD , " degrees) smaller than 360/nrays (", (360.0/inputODIM.geometry.height) ,"), setting window height=1 " );
237 pixelConf.frame.height = 1;
238 }
239
240}
241*/
242
243// NOTE: window.write() may skip ftor! ?
244template <class W>
245void DopplerWindowOp<W>::processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const {
246
247 drain::Logger mout(__FILE__, __FUNCTION__);
248
249 //DopplerDevWindow w;
250 //w.initialize();
251
252 typename W::conf_t pixelConf;
253 this->conf.setPixelConf(pixelConf, vradSrc.odim);
254 //setPixelConf(pixelConf, vradSrc.odim);
255
256 SlidingWindowOp<W> op(pixelConf);
257 mout.debug(op );
258 mout.special("provided functor: " , op.conf.getFunctorName() , '|' , op.conf.functorParameters );
259 mout.debug("pixelConf.contributionThreshold " , pixelConf.contributionThreshold );
260 mout.debug("op.conf.contributionThreshold " , op.conf.contributionThreshold );
261 //dstData.data.setGeometry(vradSrc.data.getGeometry()); // setDst() handles
262 //op.process(vradSrc.data, dstData.data);
263 //op.traverseChannel(vradSrc.data.getChannel(0), dstData.data.getChannel(0));
264 op.traverseChannel(vradSrc.data, dstData.data);
265
266 dstData.odim.prodpar = this->parameters.getValues();
267 //@~ dstData.updateTree();
268
269}
270
272/*
273class DopplerAvgOp : public DopplerWindowOp<DopplerAverageWindow> {
274public:
275
276 **
277 * \param width - radial extent of window, in metres
278 * \param height - azimuthal extent of window, in degrees
279 *
280 DopplerAvgOp(int width = 1500, double height = 3.0) :
281 DopplerWindowOp<DopplerAverageWindow>(__FUNCTION__, "Smoothens Doppler field", width, height) {
282 parameters.link("relativeScale", this->conf.relativeScale = false, "0|1");
283 odim.quantity = "VRAD"; // VRAD_C (corrected)?
284 };
285
286 virtual ~DopplerAvgOp(){};
287
288protected:
289
290 virtual inline
291 double getTypicalMin(const PolarODIM & srcODIM) const {
292 return (this->conf.relativeScale) ? -1.0 : -srcODIM.getNyquist();
293 }
294
295 virtual inline
296 double getTypicalMax(const PolarODIM & srcODIM) const {
297 return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
298 }
299
300};
301*/
302
303class DopplerAvgOp : public DopplerWindowOp<DopplerAverageWindow2> {
304public:
305
310 DopplerAvgOp(int width = 1500, double height = 3.0) :
311 DopplerWindowOp<DopplerAverageWindow2>(__FUNCTION__, "Smoothens Doppler field, providing quality", width, height) {
312 parameters.link("relativeScale", this->conf.relativeScale = false, "false|true");
313 odim.quantity = "VRAD"; // VRAD_C (corrected)?
314 };
315
316 virtual ~DopplerAvgOp(){};
317
318 virtual inline
319 void processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const {
320
321 drain::Logger mout(__FILE__, __FUNCTION__);
322 drain::FuzzyBell2<double> deviationQuality(1.0, 0.125); // 50m/s
323 DopplerAverageWindow2::conf_t pixelConf(deviationQuality);
324 // setPixelConf(pixelConf, vradSrc.odim);
325 this->conf.setPixelConf(pixelConf, vradSrc.odim);
326
327 mout.debug("radarConf: " , this->conf.widthM , 'x' , this->conf.heightD );
328 mout.debug("pixelConf: " , pixelConf.frame.width , 'x' , this->conf.frame.height );
329
331 mout.debug(op );
332 mout.warn(op );
333 mout.special("provided functor: " , op.conf.getFunctorName() , '|' , op.conf.functorParameters );
334 //mout.debug("provided functor: " , op.conf.ftor );
335
336 const drain::image::Geometry & g = vradSrc.data.getGeometry();
337
338 drain::image::Image dummy(g.getWidth(), g.getHeight());
339
340 PlainData<PolarDst> & dstQuality = dstData.getQualityData("QIND");
341 getQuantityMap().setQuantityDefaults(dstQuality, "QIND");
342 dstQuality.setGeometry(g.getWidth(), g.getHeight());
343
344 op.traverseChannel(vradSrc.data, dummy, dstData.data, dstQuality.data);
345
346 dstData.odim.prodpar = this->parameters.getValues();
347 }
348
349protected:
350
351 virtual inline
352 double getTypicalMin(const PolarODIM & srcODIM) const {
353 return (this->conf.relativeScale) ? -1.0 : -srcODIM.getNyquist();
354 }
355
356 virtual inline
357 double getTypicalMax(const PolarODIM & srcODIM) const {
358 return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
359 }
360
361};
362
363
364
365class DopplerEccentricityOp : public DopplerWindowOp<DopplerEccentricityWindow> {
366public:
367
372 DopplerEccentricityOp(int widthM = 1500, double heightD = 3.0) :
373 DopplerWindowOp<DopplerEccentricityWindow>(__FUNCTION__, "Magnitude of mean unit circle mapped Doppler speeds", widthM, heightD) {
374
375 //parameters.link("relativeScale", this->conf.relativeScale = true, "true|false");
376
377 //this->conf.relativeScale = true;
378 odim.quantity = "VRAD_DEV"; // VRAD_C ?
379 odim.scaling.scale = 1.0/200.0;
380 odim.scaling.offset = -odim.scaling.scale;
381 //odim.scaling.scale = 1.0/200.0;
382 odim.type = "C";
383 odim.nodata = 255; // TODO
384 };
385
386 virtual ~DopplerEccentricityOp(){};
387
388protected:
389
390 virtual inline
391 double getTypicalMin(const PolarODIM & srcODIM) const {
392 return 0.0;
393 }
394
395 virtual inline
396 double getTypicalMax(const PolarODIM & srcODIM) const {
397 return +1.0;
398 //return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
399 }
400
401
402};
403
404
405
406
407}
408
409
410#endif /* DOPPLERDevOP_H_ */
A smooth symmetric peak function that resembles the Gaussian bell curve. Diminishes quicker than Fuzz...
Definition Fuzzy.h:495
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Definition ReferenceMap.h:215
virtual void clear()
Removes all the elements of the map.
Definition ReferenceMap.h:390
void getValues(std::ostream &ostr) const
Dumps the values.
Definition SmartMap.h:341
void updateValues(const std::string &entries, char assignmentChar='=', char separatorChar=0)
Sets applicable values ie. modifies existing entries only. In ordered maps, skips extra entries silen...
Definition SmartMap.h:314
Definition Geometry.h:143
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition Image.h:183
Template for operators applying pipeline-like sliding window.
Definition SlidingWindowOp.h:57
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition Data.h:1275
Data structure consisting of plain data and an optional quality data.
Definition Data.h:1206
Smoothens Doppler field, providing quality computed as eccentricity.
Definition Doppler.h:229
Simple op not producing quality field.
Definition DopplerWindowOp.h:303
DopplerAvgOp(int width=1500, double height=3.0)
Definition DopplerWindowOp.h:310
Definition DopplerWindowOp.h:365
DopplerEccentricityOp(int widthM=1500, double heightD=3.0)
Definition DopplerWindowOp.h:372
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:69
DopplerWindowOp(const std::string &name, const std::string &description, int widthM, double heightD)
Definition DopplerWindowOp.h:96
ODIM metadata (quantity, gain, offset, undetect, nodata, date, time)
Definition ODIM.h:79
Essential class for storing radar data.
Definition Data.h:311
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:206
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