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
95 DopplerWindowOp(const std::string & name, const std::string & description, int widthM, double heightD) :
96 DopplerOp(name, description), conf() { //, threshold(0.5), compensatePolar(true), relativeScale(relativeScale) {
97
98 parameters.link("width", this->conf.widthM = widthM, "metres");
99 parameters.link("height", this->conf.heightD = heightD, "deg");
100 //parameters.append(conf, false); // TODO: Window::conf parameters ?
101 parameters.link("threshold", this->conf.contributionThreshold = 0.5, "percentage");
102 parameters.link("compensate", this->conf.invertPolar = false, "cart/polar[0|1]");
103 //parameters.link("relativeScale", this->conf.relativeScale = false, "0|1");
104
105
106 dataSelector.setMaxCount(1);
108 allowedEncoding.link("type", odim.type);
109 allowedEncoding.link("gain", odim.scaling.scale);
110
111 };
112
113 virtual
114 void setEncoding(const ODIM & inputODIM, PlainData<PolarDst> & dst) const;
115
116
117 virtual
118 double getTypicalMin(const PolarODIM & srcODIM) const = 0;
119
120 virtual
121 double getTypicalMax(const PolarODIM & srcODIM) const = 0;
122
124 /*
125 void setPixelConf(typename W::conf_t & pixelConf, const PolarODIM & inputODIM) const {
126 this->conf.setPixelConf(pixelConf, inputODIM);
127 }
128 */
129
130};
131
132
133
134template <class W>
136
138
139 dst.odim.quantity = odim.quantity;
140
142 typeRef.link("type", dst.odim.type = odim.type);
143 typeRef.updateValues(targetEncoding);
144 dst.data.setType(dst.odim.type);
145
146 if (odim.scaling.scale != 0.0){ // NOTE: now dst.odim.scaling.scale at least default (1.0)
147 mout.warn("Init with ODIM: " , EncodingODIM(odim) );
148 //ProductOp::
149 applyODIM(dst.odim, odim);
150 }
151 else {
152 // const double max = (this->conf.relativeScale) ? 1.0 : inputODIM.NI;
153 if (drain::Type::call<drain::typeIsSmallInt>(dst.data.getType())){
154 dst.setPhysicalRange(getTypicalMin(inputODIM), getTypicalMax(inputODIM));
155 //mout.note(EncodingODIM(inputODIM) );
156 mout.debug("small int: " , EncodingODIM(dst.odim) );
157 mout.debug2("small int: " , dst.data );
158 // dstData.data.setScaling(dstData.odim.scaling.scale, dstData.odim.scaling.offset);
159 }
160 else {
161 if (drain::Type::call<drain::typeIsInteger>(dst.data.getType()))
162 mout.warn("large int" );
163 }
164 dst.odim.distinguishNodata(); // change undetect
165 }
166
167 //ProductBase::applyODIM(dst.odim, inputODIM, true); // New. Use defaults if still unset
168 dst.odim.completeEncoding( targetEncoding);
169
170 dst.data.setScaling(dst.odim.scaling); // needed?
171 //dst.data.setScaling(dst.odim.scaling.scale, dst.odim.scaling.offset);
172 mout.debug("final dst: " , dst.data );
173}
174
175
176template <class W>
177void DopplerWindowOp<W>::processDataSet(const DataSet<PolarSrc> & srcSweep, DataSet<PolarDst> & dstProduct) const {
178
179 drain::Logger mout(__FILE__, __FUNCTION__);
180
181 //const drain::RegExp quantityRe(dataSelector.getQuantity()); // "VRADH?";
182
183 const Data<PolarSrc> & vradSrc = srcSweep.getData(dataSelector.getQuantitySelector()); // (quantityRe); // consider data selector?
184
185 if (vradSrc.data.isEmpty()){
186 mout.warn("VRAD missing" );
187 return;
188 }
189
190 if (vradSrc.odim.getNyquist() == 0) {
191 mout.warn("VRAD unusable, vradSrc.odim.getNyquist() == 0" );
192 return;
193 }
194
195 Data<PolarDst> & dstData = dstProduct.getData(odim.quantity); // quality data?
196
197 dstData.odim.updateLenient(vradSrc.odim);
198 //dstData.odim.NI = vradSrc.odim.NI;
199 initDst(vradSrc.odim, dstData);
200
201 dstData.data.fill(dstData.odim.undetect); // NEW 2019/11
202
203 processData(vradSrc, dstData);
204 //mout.warn("after:" , dstData.data.getScaling() );
205
206
207 //@ dstProduct.updateTree(dstData.odim);
208
209
210}
211
212/*
213template <class W>
214void DopplerWindowOp<W>::setPixelConf(typename W::conf_t & pixelConf, const PolarODIM & inputODIM) const {
215
216 drain::Logger mout(__FILE__, __FUNCTION__);
217
218 // pixelConf = this->conf; PROBLEM: ftor prevents op=
219 pixelConf.widthM = this->conf.widthM;
220 pixelConf.heightD = this->conf.heightD;
221 pixelConf.updatePixelSize(inputODIM);
222 pixelConf.invertPolar = this->conf.invertPolar;
223 pixelConf.contributionThreshold = this->conf.contributionThreshold;
224 pixelConf.relativeScale = this->conf.relativeScale;
225
226 if (pixelConf.frame.width == 0){
227 mout.note(this->conf.frame.width );
228 mout.note(this->conf.widthM );
229 mout.note(*this );
230 mout.warn("Requested width (" , pixelConf.widthM , " meters) smaller than rscale (", inputODIM.rscale ,"), setting window width=1 " );
231 pixelConf.frame.width = 1;
232 }
233
234 if (pixelConf.frame.height == 0){
235 mout.warn("Requested height (" , pixelConf.heightD , " degrees) smaller than 360/nrays (", (360.0/inputODIM.geometry.height) ,"), setting window height=1 " );
236 pixelConf.frame.height = 1;
237 }
238
239}
240*/
241
242// NOTE: window.write() may skip ftor! ?
243template <class W>
244void DopplerWindowOp<W>::processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const {
245
246 drain::Logger mout(__FILE__, __FUNCTION__);
247
248 //DopplerDevWindow w;
249 //w.initialize();
250
251 typename W::conf_t pixelConf;
252 this->conf.setPixelConf(pixelConf, vradSrc.odim);
253 //setPixelConf(pixelConf, vradSrc.odim);
254
255 SlidingWindowOp<W> op(pixelConf);
256 mout.debug(op );
257 mout.special("provided functor: " , op.conf.getFunctorName() , '|' , op.conf.functorParameters );
258 mout.debug("pixelConf.contributionThreshold " , pixelConf.contributionThreshold );
259 mout.debug("op.conf.contributionThreshold " , op.conf.contributionThreshold );
260 //dstData.data.setGeometry(vradSrc.data.getGeometry()); // setDst() handles
261 //op.process(vradSrc.data, dstData.data);
262 //op.traverseChannel(vradSrc.data.getChannel(0), dstData.data.getChannel(0));
263 op.traverseChannel(vradSrc.data, dstData.data);
264
265 dstData.odim.prodpar = this->parameters.getValues();
266 //@~ dstData.updateTree();
267
268}
269
271/*
272class DopplerAvgOp : public DopplerWindowOp<DopplerAverageWindow> {
273public:
274
275 **
276 * \param width - radial extent of window, in metres
277 * \param height - azimuthal extent of window, in degrees
278 *
279 DopplerAvgOp(int width = 1500, double height = 3.0) :
280 DopplerWindowOp<DopplerAverageWindow>(__FUNCTION__, "Smoothens Doppler field", width, height) {
281 parameters.link("relativeScale", this->conf.relativeScale = false, "0|1");
282 odim.quantity = "VRAD"; // VRAD_C (corrected)?
283 };
284
285 virtual ~DopplerAvgOp(){};
286
287protected:
288
289 virtual inline
290 double getTypicalMin(const PolarODIM & srcODIM) const {
291 return (this->conf.relativeScale) ? -1.0 : -srcODIM.getNyquist();
292 }
293
294 virtual inline
295 double getTypicalMax(const PolarODIM & srcODIM) const {
296 return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
297 }
298
299};
300*/
301
302class DopplerAvgOp : public DopplerWindowOp<DopplerAverageWindow2> {
303public:
304
309 DopplerAvgOp(int width = 1500, double height = 3.0) :
310 DopplerWindowOp<DopplerAverageWindow2>(__FUNCTION__, "Smoothens Doppler field, providing quality", width, height) {
311 parameters.link("relativeScale", this->conf.relativeScale = false, "false|true");
312 odim.quantity = "VRAD"; // VRAD_C (corrected)?
313 };
314
315 virtual ~DopplerAvgOp(){};
316
317 virtual inline
318 void processData(const Data<PolarSrc> & vradSrc, Data<PolarDst> & dstData) const {
319
320 drain::Logger mout(__FILE__, __FUNCTION__);
321 drain::FuzzyBell2<double> deviationQuality(1.0, 0.125); // 50m/s
322 DopplerAverageWindow2::conf_t pixelConf(deviationQuality);
323 // setPixelConf(pixelConf, vradSrc.odim);
324 this->conf.setPixelConf(pixelConf, vradSrc.odim);
325
326 mout.debug("radarConf: " , this->conf.widthM , 'x' , this->conf.heightD );
327 mout.debug("pixelConf: " , pixelConf.frame.width , 'x' , this->conf.frame.height );
328
330 mout.debug(op );
331 mout.warn(op );
332 mout.special("provided functor: " , op.conf.getFunctorName() , '|' , op.conf.functorParameters );
333 //mout.debug("provided functor: " , op.conf.ftor );
334
335 const drain::image::Geometry & g = vradSrc.data.getGeometry();
336
337 drain::image::Image dummy(g.getWidth(), g.getHeight());
338
339 PlainData<PolarDst> & dstQuality = dstData.getQualityData("QIND");
340 getQuantityMap().setQuantityDefaults(dstQuality, "QIND");
341 dstQuality.setGeometry(g.getWidth(), g.getHeight());
342
343 op.traverseChannel(vradSrc.data, dummy, dstData.data, dstQuality.data);
344
345 dstData.odim.prodpar = this->parameters.getValues();
346 }
347
348protected:
349
350 virtual inline
351 double getTypicalMin(const PolarODIM & srcODIM) const {
352 return (this->conf.relativeScale) ? -1.0 : -srcODIM.getNyquist();
353 }
354
355 virtual inline
356 double getTypicalMax(const PolarODIM & srcODIM) const {
357 return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
358 }
359
360};
361
362
363
364class DopplerEccentricityOp : public DopplerWindowOp<DopplerEccentricityWindow> {
365public:
366
370 DopplerEccentricityOp(int widthM = 1500, double heightD = 3.0) :
371 DopplerWindowOp<DopplerEccentricityWindow>(__FUNCTION__, "Magnitude of mean unit circle mapped Doppler speeds", widthM, heightD) {
372
373 //parameters.link("relativeScale", this->conf.relativeScale = true, "true|false");
374
375 //this->conf.relativeScale = true;
376 odim.quantity = "VRAD_DEV"; // VRAD_C ?
377 odim.scaling.scale = 1.0/200.0;
378 odim.scaling.offset = -odim.scaling.scale;
379 //odim.scaling.scale = 1.0/200.0;
380 odim.type = "C";
381 odim.nodata = 255; // TODO
382 };
383
384 virtual ~DopplerEccentricityOp(){};
385
386protected:
387
388 virtual inline
389 double getTypicalMin(const PolarODIM & srcODIM) const {
390 return 0.0;
391 }
392
393 virtual inline
394 double getTypicalMax(const PolarODIM & srcODIM) const {
395 return +1.0;
396 //return (this->conf.relativeScale) ? +1.0 : +srcODIM.getNyquist();
397 }
398
399
400};
401
402
403
404
405}
406
407
408#endif /* DOPPLERDevOP_H_ */
const std::string description
Brief, human-readable description of this bean.
Definition BeanLike.h:309
map_t parameters
Parameters (name -> linked variable), typically linked to member variables of the derived class.
Definition BeanLike.h:313
const std::string name
Name of this bean, typically also the name of the (derived) class.
Definition BeanLike.h:306
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:326
Definition ReferenceMap.h:215
virtual void clear()
Removes all the elements of the map.
Definition ReferenceMap.h:387
void getValues(std::ostream &ostr) const
Dumps the values.
Definition SmartMap.h:341
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:1293
Smoothens Doppler field, providing quality computed as eccentricity.
Definition Doppler.h:229
Simple op not producing quality field.
Definition DopplerWindowOp.h:302
DopplerAvgOp(int width=1500, double height=3.0)
Definition DopplerWindowOp.h:309
Definition DopplerWindowOp.h:364
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
Structure for data storage type, scaling and marker codes. Does not contain quantity.
Definition EncodingODIM.h:70
ODIM metadata (quantity, gain, offset, undetect, nodata, date, time)
Definition ODIM.h:79
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:210
MD odim
The default data parameters for encoding output (the product).
Definition RadarProductOp.h:101
Definition AltitudeOp.cpp:42
QuantityMap & getQuantityMap()
Definition QuantityMap.cpp:282