Loading...
Searching...
No Matches
RadarAccumulator.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#ifndef RADAR_ACCUMULATOR_H
32#define RADAR_ACCUMULATOR_H
33
34
35#include <sstream>
36
37// #include <drain/image/Sampler.h>
38#include <drain/image/AccumulatorGeo.h>
39
40
41#include "data/ODIM.h"
42#include "data/ODIMPath.h"
43#include "data/Data.h"
44#include "data/DataSelector.h"
45#include "data/DataCoder.h"
46#include "data/QuantityMap.h"
47// #include "product/RadarProductOp.h"
48#include "Geometry.h"
49
50
51namespace rack {
52
54/*
55 * with Cart / polar linkage
56 *
57 * getProperties("where:proj", comp.projDef)
58 * getProperties("where:xsize", comp.width ?)
59 * getProperties("where:nbins", comp.width ?)
60 *
61 */
62
64
65
66public:
67
68 inline
70
71 inline
74
75 void extractFinally(const drain::image::Accumulator & accumulator, drain::image::Accumulator::FieldType field,
76 const ODIM &srcODIM, const DataCoder & dataCoder,
77 ODIM &dstODIM, drain::image::Image & dstImage, const drain::Rectangle<int> & cropArea);
78
81 // DataSelector dataSelector(ODIMPathElem::DATA);
82 // dataSelector.pathMatcher.setElems(ODIMPathElem::DATA);
83
84 typedef std::map<int,std::string> legend_t;
85 legend_t legend;
86
87
90
92
95 size_t counter;
96
97 inline
98 const std::string & getTargetEncoding(){
99 return targetEncoding;
100 }
101
102
103protected:
104
105 static
106 bool checkCompositingMethod(const AccumulationMethod & rule, const ODIM & dataODIM);
107
108 std::string targetEncoding;
109
110
111};
112
114
120template <class AC, class OD>
121//class RadarAccumulator : public AC { // deprecating AC!
122class RadarAccumulator : public RadarAccumulatorBase, public AC {
123
124public:
125
130
131
133 RadarAccumulator() { // , undetectValue(-52.0) {
134 odim.type.clear();
135 odim.ACCnum = 0; // NEW
136 }
137
138 virtual
140
142 /*
143 * Counter example: this method is \i not called when polar data is added to a Cartesian composite.
144 *
145 * \param i0 - offset in horizontal direction
146 * \param j0 - offset in vertical direction
147 */
148 void addData(const pdata_src_t & srcData, const pdata_src_t & srcQuality, double weight, int i0, int j0);
149
151 /*
152 *
153 * Counter example: this method is \i not called when polar data is added to a Cartesian composite.
154 */
155 void addData(const pdata_src_t & srcData, const pdata_src_t & srcQuality, const pdata_src_t & srcCount);
156
157
162 // TODO: remove this (use the new ones)
163 void extractOLD(const OD & odimOut, DataSet<DstType<OD> > & dstProduct,
164 const std::string & fields, const drain::Rectangle<int> & crop = {0,0,0,0}) const;
165
166 inline
167 void extract(DataSet<DstType<OD> > & dstProduct, const std::string & fieldStr, const std::string & encoding="C", const drain::Rectangle<int> & cropArea={0,0}){
168 drain::image::Accumulator::FieldList fields;
169 drain::image::Accumulator::getFields(fieldStr, fields);
170 extract(dstProduct, fields, encoding, cropArea);
171 }
172
173 void extract(DataSet<DstType<OD> > & dstProduct, const drain::image::Accumulator::FieldList & fields, const std::string & encoding="C", const drain::Rectangle<int> & cropArea={0,0});
174
175 pdata_dst_t & extract(DataSet<DstType<OD> > & dstProduct, field_t field = field_t::DATA, const std::string & encoding="C", const drain::Rectangle<int> & cropArea={0,0});
176
177 // void extractDraft(ODIM & odim, drain::image::Image & dstData, field_t field, const std::string & encoding="", const drain::Rectangle<int> & cropArea={0,0});
178
179
181 /*
182 * Helps in warning if input data does not match the expected / potential targetEncoding
183 */
184 // Note: consider rack::ODIM. And perhaps ODIM to inherit FlexibleVariableMap.
186
187
188
190 void setTargetEncoding(const std::string & encoding);
191
192 inline
193 void consumeTargetEncoding(std::string & encoding){
194 setTargetEncoding(encoding);
195 encoding.clear();
196 }
197
198
199
200 virtual inline
201 std::ostream & toStream(std::ostream & ostr) const {
202
203 // std::cerr << __FILE__ << '@' << __LINE__ << std::endl;
204 this->AC::toStream(ostr);
205 ostr << ' ';
206 // std::cerr << __FILE__ << '@' << __LINE__ << std::endl;
207 odim.toStream(ostr);
208 // std::cerr << __FILE__ << '@' << __LINE__ << " (end)" << std::endl;
209 return ostr;
210 }
211
213 //bool checkCompositingMethod(const ODIM & srcODIM) const;
214 inline
215 bool checkCompositingMethod(const ODIM & dataODIM){
216 return RadarAccumulatorBase::checkCompositingMethod(this->getMethod(), dataODIM);
217 }
218
219
220
221};
222
223
224template <class AC, class OD>
225void RadarAccumulator<AC,OD>::setTargetEncoding(const std::string & encoding){
226
227 drain::Logger mout(__FILE__, __FUNCTION__);
228
229 targetEncoding = encoding;
230
231 if (encoding.empty()){
232 return;
233 }
234
235 std::string quantityPrev = odim.quantity;
236 // if (odim.quantity.empty()){
237 /*
238 ODIM m;
239 m.link("what:quantity", odim.quantity); // appends
240 m.addShortKeys();
241 m.updateValues(encoding);
242 */
243 //}
244
245 //odim.link("what:quantity", odim.quantity);
246 //m.addShortKeys();
247 odim.addShortKeys();
248 odim.updateValues(encoding);
249
250
251 if (!quantityPrev.empty()){
252 if (odim.quantity != quantityPrev){
253 mout.warn("Quantity changed from [", quantityPrev, "] to [", odim.quantity, "]");
254 }
255 else {
256 mout.info("Confirming quantity [", odim.quantity, "] explicitly");
257 }
258 }
259
260 // mout.attention("Quantity: [", quantityPrev, "] -> [", odim.quantity, "]");
261 mout.attention("Target encoding: [", encoding, "] odim: ", odim); //, "]");
262
263
264}
265
266template <class AC, class OD>
267void RadarAccumulator<AC,OD>::addData(const pdata_src_t & srcData, const pdata_src_t & srcQuality, double weight, int i0, int j0){
268
269 drain::Logger mout(__FILE__, __FUNCTION__);
270
271 // mout.attention("START ", EncodingODIM(srcData.odim));
272
273 if (!srcQuality.data.isEmpty()){
274 mout.info("Quality data available with input; using quality as weights in compositing.");
275 DataCoder converter(srcData.odim, srcQuality.odim);
276 // uses also DataCoder::undetectQualityCoeff
277 AC::addData(srcData.data, srcQuality.data, converter, weight, i0, j0);
278 }
279 else {
280 mout.info("No quality data available with input, ok.");
281 ODIM qualityOdim; // dummy
282 getQuantityMap().setQuantityDefaults(qualityOdim, "QIND");
283
284 DataCoder converter(srcData.odim, qualityOdim);
285 // uses also DataCoder::undetectQualityCoeff
286 AC::addData(srcData.data, converter, weight, i0, j0);
287 }
288
289 // mout.attention("END1 ", EncodingODIM(this->odim));
290 odim.updateLenient(srcData.odim); // Time, date, new
291 // mout.attention("END2 ", EncodingODIM(this->odim));
292
293 counter += std::max(1L, srcData.odim.ACCnum);
294 // odim.ACCnum += std::max(1L, srcData.odim.ACCnum); wrong
295 // odim.ACCnum = counter; // TODO remove counter?
296
297 //mout.note("after: " , this->odim );
298
299}
300
301template <class AC, class OD>
302void RadarAccumulator<AC,OD>::addData(const pdata_src_t & srcData, const pdata_src_t & srcQuality, const pdata_src_t & srcCount){
303
304 drain::Logger mout(__FILE__, __FUNCTION__);
305 // mout.info("Quality data available with input; using quality as weights in compositing.");
306 DataCoder converter(srcData.odim, srcQuality.odim);
307 AC::addData(srcData.data, srcQuality.data, srcCount.data, converter);
308
309 odim.updateLenient(srcData.odim); // Time, date, new
310 counter = std::max(1L, srcData.odim.ACCnum); // correct
311 // odim.ACCnum += std::max(1L, srcData.odim.ACCnum); // wrong
312}
313
314
315/*
316template <class AC, class OD>
317bool RadarAccumulator<AC,OD>::checkCompositingMethod(const ODIM & dataODIM) const {
318
319 drain::Logger mout(__FILE__, __FUNCTION__);
320
321 mout.debug("start, quantity=" , dataODIM.quantity );
322
323 const AccumulationMethod & rule = this->getMethod();
324 if (rule.getName() == "WAVG"){
325
326 const drain::ReferenceMap & wavgParams = rule.getParameters();
327 const double p = wavgParams.get("p", 1.0);
328 const double p2 = p/2.0;
329 mout.info(rule , ", min=", dataODIM.getMin() );
330
331 if ((p2 - floor(p2)) == 0.0){
332 mout.info("WAVG with p=" , p , " = 2N, positive pow() results" );
333 const Quantity & q = getQuantityMap().get(dataODIM.quantity);
334 if (q.hasUndetectValue()){
335 const double bias = wavgParams.get("bias", 0.0);
336 if (bias > q.undetectValue){
337 mout.warn("WAVG with p=" , p ," = 2N, undetectValue=" , q.undetectValue , " < bias=", bias );
338 mout.warn("consider adjusting bias(", bias ,") down to quantity (" , dataODIM.quantity , ") zero: " , q.undetectValue );
339 //rule.setParameter("bias", q.undetectValue);
340 return true;
341 }
342 }
343 }
344 }
345
346 return false;
347
348
349}
350*/
351template <class AC, class OD>
352//void Composite::extract(DataSet<DstType<CartesianODIM> > & dstProduct, const FieldList & fields, const std::string & encoding, const drain::Rectangle<int> & cropArea){
353void RadarAccumulator<AC,OD>::extract(DataSet<DstType<OD> > & dstProduct, const drain::image::Accumulator::FieldList & fields, const std::string & encoding, const drain::Rectangle<int> & cropArea){
354
355 drain::Logger mout(__FILE__, __FUNCTION__);
356
357 for (drain::image::Accumulator::FieldType field: fields) {
358
359 pdata_dst_t & dstData = extract(dstProduct, field, encoding, cropArea);
360
361 if (ODIM::versionFlagger.isSet(ODIM::RACK_EXTENSIONS) && !legend.empty()){
362 mout.experimental("Copying (moving) legend for ", field);
363 dstData.getWhat()["legend"] = drain::sprinter(legend, "|", ",", ":").str();
364 legend.clear();
365 }
366 }
367
368
369}
370
371
372template <class AC, class OD>
374 const std::string & encoding, const drain::Rectangle<int> & cropArea){
375
376 drain::Logger mout(__FILE__, __FUNCTION__);
377
378 mout.debug("extracting FIELD: ", field);
379
380 char fieldChar = (char)(((int)field)&127);
381 if (fieldChar != drain::image::Accumulator::getFieldChar(field)){
382 mout.fail("program error: ", field, '=', fieldChar, "!=", drain::image::Accumulator::getFieldChar(field));
383 }
384
385 //const std::type_info & t = drain::Type::getTypeInfo('C'); // drain::Type::getTypeInfo(odimOut.type);
386 if (!cropArea.empty()){
387 mout.note("Applying cropping: bbox=", cropArea, " [pix] from ", this->accArray.getGeometry()); // this->getFrameWidth(), 'x', this->getFrameHeight());
388 }
389
390 const QuantityMap & qm = getQuantityMap();
391
397 //bool DATA_SPECIFIC_QUALITY = false;
398 //mout.experimental<LOG_NOTICE>("EncodingODIM THIS = ", this->odim);
399
400 ODIM odimData;
401 drain::SmartMapTools::updateValues(odimData, this->odim); // Note: copies, to support extraction with different encodings
402 // This should be unneeded... // odimData.quantity = this->odim.quantity;
403 ODIM odimQuality;
404 // mout.experimental<LOG_NOTICE>("EncodingODIM SRC = ", EncodingODIM(odimData));
405
407
408 // TODO: clean confusing mixture of referring to dataCoder.dataODIM <==> odimData
409 DataCoder dataCoder(odimData, odimQuality); // (will use only either odim!)
410
411 {
412 mout.attention("extracting field '", field, "'");
413
414 /*
415 if (odimData.quantity.empty()){
416 odimData.quantity = "UNKNOWN"; // ok; for example --cPlotFile carries no information on quantity
417 mout.note("quantity=", odimData.quantity);
418 }
419 */
420 mout.debug(DRAIN_LOG_VAR(dataCoder));
421 mout.debug2(DRAIN_LOG_VAR(dataCoder.dataODIM));
422 mout.debug2(DRAIN_LOG_VAR(dataCoder.qualityODIM));
423
425
426 // Note: encoding is used only for DATA to avoid ambiguous setting for multiple request of fields: DATA,WEIGHT,COUNT, ...
427 if (field == field_t::DATA){
428
429 //pdata_dst_t & dstData = dstProduct.getData(this->odim.quantity);
430
431 // TODO: clean confusing mixture of dataCoder.dataODIM <==> odimData
432
433
434 // Update 1/2: from initial values to this "instantaneous" extraction
435 drain::SmartMapTools::updateValues(odimData, this->odim); // lazy (qualityData does not need)
436
437 mout.debug("extracting DATA/" , field, " [", odimData.quantity, ']');
438
439 if (!encoding.empty()){
440 mout.accept("User-defined encoding for data [", odimData.quantity, "]: ", encoding);
441 //odimData.completeEncoding( encoding);
442 odimData.completeEncoding(encoding);
443 }
444 else if (!getTargetEncoding().empty()){
445 mout.ok<LOG_NOTICE>("Using initial/default encoding for data [", odimData.quantity, "]: ", getTargetEncoding());
446 // odimData.completeEncoding( getTargetEncoding());
447 odimData.completeEncoding(getTargetEncoding());
448 }
449
450 if (odimData.quantity.empty()){
451 mout.error("unspecified quantity");
452 }
453
454 pdata_dst_t & dstData = dstProduct.getData(odimData.quantity);
455
456 // Update 2/2: copy "instantaneous", maybe adjusted encoding to retrieved data
457 extractFinally(*this, field, odimData, dataCoder, dstData.odim, dstData.data, cropArea);
458 return dstData;
459 /*
460 drain::SmartMapTools::updateValues(dstData.odim, odimData);
461
462 if (dataCoder.dataODIM.isSet()){
463 dstData.data.setType(odimData.type);
464 mout.debug3("dstData: " , dstData );
465 this->Accumulator::extractField(field, dataCoder, dstData.data, cropArea);
466 return dstData;
467 }
468 else {
469 // Note: this is also checked by Accumulator, but better diagnostics (ODIM) here:
470 mout.error("Target encoding unset: gain=", dataCoder.dataODIM.scaling.scale, ", type=", dataCoder.dataODIM.type);
471 return dstData;
472 }
473 */
474
475 }
476 else {
477
478 switch (field){
479 case field_t::WEIGHT_DS:
480 case field_t::WEIGHT:
481 odimQuality.quantity = "QIND";
482 break;
483 case field_t::COUNT_DS:
484 case field_t::COUNT:
485 odimQuality.quantity = "COUNT";
486 break;
487 case field_t::DEVIATION:
488 odimQuality.quantity = this->odim.quantity + "DEV";
489 break;
490 default:
491 mout.error("Unsupported field marker: ", field, "='", fieldChar, "'");
492 //mout.error("Unsupported field marker: ", FieldFlagger::getKeysNEW2(field));
493 }
494
495 mout.debug("extracting QUALITY/" , field, " [", odimQuality.quantity, ']');
496
497 if (qm.hasQuantity(odimQuality.quantity)){
498 qm.setQuantityDefaults(odimQuality, odimQuality.quantity, odimQuality.type);
499 mout.accept<LOG_DEBUG>("found quantityConf[", odimQuality.quantity, "], type=", odimQuality.type);
500 mout.special<LOG_DEBUG>("Quality: ", EncodingODIM(odimQuality));
501 mout.special<LOG_DEBUG>("Quality: ", odimQuality);
502 }
503 else if (!encoding.empty()){
504 mout.accept<LOG_INFO>("User-defined encoding for quality [", odimQuality.quantity, "]: ", encoding);
505 odimQuality.completeEncoding(encoding);
506 mout.debug("User-defined encoding for QUALITY: -> ", odimQuality);
507 }
508 else {
509 // mout.experimental("No predefined scaling for ", odimQuality.quantity);
510 /*
511 const std::type_info & t = drain::Type::getTypeInfo(odimQuality.type);
512 odimQuality.scaling.scale *= 20.0; // ?
513 odimQuality.scaling.offset = round(drain::Type::call<drain::typeMin, double>(t) + drain::Type::call<drain::typeMax, double>(t))/2.0;
514 if (encoding.empty()){
515 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using somewhat arbitrary scaling:" );
516 mout.special("Quality: ", EncodingODIM(odimQuality));
517 }
518 */
519 odimQuality.setType(typeid(float));
520 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using float" );
521 mout.special("Quality: ", EncodingODIM(odimQuality));
522
523 }
524 // else auto-scale?
525
526
527 typedef QualityDataSupport<DstType<OD> > q_support_t;
528 q_support_t & qualityOwner = Accumulator::isSpecific(field) ? (q_support_t &) dstProduct.getData(odimData.quantity) : (q_support_t &) dstProduct;
529 pdata_dst_t & dstQuality = qualityOwner.getQualityData(odimQuality.quantity);
530
531
532 // NOTE similarity... but fct still would need separating (dataCoder, odimData, odimQuality, odimNow, field, crop)
533 extractFinally(*this, field, odimQuality, dataCoder, dstQuality.odim, dstQuality.data, cropArea);
534 return dstQuality;
535 /*
536 drain::SmartMapTools::updateValues(dstQuality.odim, odimQuality);
537 // if (dataCoder.squalityODIM.isSet()){
538 if (dstQuality.odim.isSet()){
539 // dstQuality.data.setType(odimData.type); // <- this was probably wrong
540 dstQuality.data.setType(dstQuality.odim.type); // <- this was probably wrong
541 mout.debug3("dstData: " , dstQuality );
542 this->Accumulator::extractField(fieldChar, dataCoder, dstQuality.data, cropArea);
543 return dstQuality;
544 }
545 else {
546 // Note: this is also checked by Accumulator, but better diagnostics (ODIM) here:
547 mout.error("Target encoding unset: gain=", dstQuality.odim.scaling.scale, ", type=", dstQuality.odim.type);
548 //mout.error("Target encoding unset: gain=", dataCoder.qualityODIM.scaling.scale, ", type=", dataCoder.qualityODIM.type);
549 return dstQuality;
550 }
551 */
552
553 }
554
555 // mout.debug("updating local tree attributes");
556
557 }
558
559
560 // mout.debug("updating local tree attributes" );
561 // mout.debug("finished" );
562
563}
564
565// TODO: remove this (use the new ones)
566template <class AC, class OD>
567void RadarAccumulator<AC,OD>::extractOLD(const OD & odimOut, DataSet<DstType<OD> > & dstProduct,
568 const std::string & fields, const drain::Rectangle<int> & crop) const {
569 // , const drain::Rectangle<double> & bbox) const {
570
571 drain::Logger mout(__FILE__, __FUNCTION__);
572
573 const std::type_info & t = drain::Type::getTypeInfo(odimOut.type);
574
575 typedef enum {DATA,QUALITY} datatype;
576
577 OD odimData;
578 odimData = odimOut;
579 odimData.scaling.scale = 0.0; // ?
580
581 const QuantityMap & qm = getQuantityMap();
582
583 // Determines if quality is stored in
584 // /dataset1/quality1/
585 // or
586 // /dataset1/data1/quality1/
587 //
588 bool DATA_SPECIFIC_QUALITY = false;
589
590 // Consider redesign, with a map of objects {quantity, type,}
591 for (size_t i = 0; i < fields.length(); ++i) {
592
593 ODIM odimQuality;
594 odimQuality.quantity = "QIND";
595
596 // std::stringstream dataPath;
597
598 datatype type = DATA;
599 char field = fields.at(i);
600 switch (field) {
601 case '/':
602 DATA_SPECIFIC_QUALITY = true;
603 continue;
604 break; // unneeded?
605 case 'm': // ???
606 case 'D':
607 case 'p': // ???
608 mout.warn() << "non-standard layer code; use 'd' for 'data' instead" << mout.endl;
609 // no break
610 case 'd':
611 type = DATA;
612 odimData = odimOut; // consider update
613 qm.setQuantityDefaults(odimQuality, "QIND"); // ?
614 odimQuality.quantity = "QIND";
615 break;
616 case 'c':
617 type = QUALITY;
618 qm.setQuantityDefaults(odimQuality, "COUNT");
619 odimQuality.quantity = "COUNT";
620 break;
621 case 'C':
622 type = QUALITY;
623 qm.setQuantityDefaults(odimQuality, "COUNT", "d");
624 odimQuality.quantity = "COUNT";
625 break;
626 // case 'q': // consider
627 case 'w':
628 // no break
629 type = QUALITY;
630 odimData = odimOut; // (Because converter needs both data and weight to encode weight?)
631 qm.setQuantityDefaults(odimQuality, "QIND", "C");
632 odimQuality.quantity = "QIND";
633 //odimQuality.undetect = 256;
634 //odimQuality.nodata = -1; // this is good, because otherwise nearly-undetectValue-quality CAPPI areas become no-data.
635 break;
636 case 'W':
637 mout.warn("experimental: quality [QIND] type copied from data [" , odimOut.quantity , ']' );
638 // no break
639 type = QUALITY;
640 odimData = odimOut; // (Because converted needs both data and weight to encode weight?)
641 qm.setQuantityDefaults(odimQuality, "QIND", odimOut.type);
642 odimQuality.quantity = "QIND";
643 //odimQuality.undetect = 256;
644 //odimQuality.nodata = -1; // this is good, because otherwise nearly-undetectValue-quality CAPPI areas become no-data.
645 break;
646 case 's':
647 type = QUALITY;
648 odimQuality = odimOut;
649 odimQuality.quantity += "DEV";
650 if (qm.hasQuantity(odimQuality.quantity)){
651 qm.setQuantityDefaults(odimQuality, odimQuality.quantity, odimQuality.type);
652 mout.accept<LOG_NOTICE>("found quantyConf[", odimQuality.quantity, "], type=", odimQuality.type);
653 //mout.special("Quality: ", EncodingODIM(odimQuality));
654 mout.special("Quality: ", EncodingODIM(odimQuality));
655 mout.special("Quality: ", odimQuality);
656 }
657 else {
658 odimQuality.scaling.scale *= 20.0; // ?
659 //const std::type_info & t = Type::getType(odimFinal.type);
660 odimQuality.scaling.offset = round(drain::Type::call<drain::typeMin, double>(t) + drain::Type::call<drain::typeMax, double>(t))/2.0;
661 //odimQuality.offset = round(drain::Type::call<drain::typeMax,double>(t) + drain::Type::getMin<double>(t))/2.0; // same as data!
662 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using somewhat arbitary scaling:" );
663 mout.special("Quality: ", EncodingODIM(odimQuality));
664 }
665 break;
666 default:
667 mout.error("Unsupported field code: '", field, "'");
668 break;
669 }
670
671 mout.debug("extracting field ", field);
672
673 if (!crop.empty()){
674 mout.experimental("Applying cropping: bbox=", crop, " [pix]");
675 }
676
677 if (type == DATA){
678 mout.debug("target: " , EncodingODIM(odimData) );
679 }
680 else if (type == QUALITY){
681 mout.debug("target: " , EncodingODIM(odimQuality) );
682 }
683
684 if (odimData.quantity.empty()){
685 odimData.quantity = "UNKNOWN"; // ok; for example --cPlotFile carries no information on quantity
686 mout.note("quantity=", odimData.quantity);
687 }
688
689 //PlainData<DstType<OD> >
690 mout.debug("searching dstData... DATA=", (type == DATA));
691 //pdata_dst_t & dstData = (type == DATA) ? dstProduct.getData(odimFinal.quantity) : dstProduct.getQualityData(odimQuality.quantity);
692 //mout .debug3() << "dstData: " << dstData << mout.endl;
693
694 //DataDst dstData(dataGroup); // FIXME "qualityN" instead of dataN creates: /dataset1/qualityN/quality1/data
695 //mout.warn("odimFinal: " , odimFinal );
696 mout.debug("odimData: " , EncodingODIM(odimData) );
697 DataCoder dataCoder(odimData, odimQuality); // (will use only either odim!)
698 mout.debug("dataCoder: ", dataCoder);
699 mout.debug2("dataCoder: data: ", dataCoder.dataODIM);
700 mout.debug2("dataCoder: qind: ", dataCoder.qualityODIM);
701
702 if (!crop.empty()){
703 mout.unimplemented("crop ", crop, ", dstData.data resize + Accumulator::extractField ");
704 }
705
706 if (type == DATA){
707 mout.debug("DATA/" , field, " [", odimData.quantity, ']');
708 //mout.warn(dstData.odim );
709 pdata_dst_t & dstData = dstProduct.getData(odimData.quantity);
710 dstData.odim.importMap(odimData);
711 dstData.data.setType(odimData.type);
712 mout.debug3("dstData: " , dstData );
713 //mout.debug("quantity=" , dstData.odim.quantity );
714 this->Accumulator::extractField(field, dataCoder, dstData.data, crop);
715 }
716 else {
717 mout.debug("QUALITY/" , field , " [", odimQuality.quantity, ']');
718 //pdata_dst_t & dstData = dstProduct.getData(odimFinal.quantity);
719 typedef QualityDataSupport<DstType<OD> > q_data_t;
720 q_data_t & qualityOwner = (DATA_SPECIFIC_QUALITY) ? (q_data_t &) dstProduct.getData(odimData.quantity) : (q_data_t &) dstProduct;
721 pdata_dst_t & dstData = qualityOwner.getQualityData(odimQuality.quantity);
722 dstData.odim.updateFromMap(odimQuality);
723 mout.debug3("dstData: " , dstData );
724 this->Accumulator::extractField(field, dataCoder, dstData.data, crop);
725 }
726
727
728 // mout.debug("updating local tree attributes");
729
730 }
731
732
733 // mout.debug("updating local tree attributes" );
734 // mout.debug("finished" );
735
736}
737
738
739} // rack::
740
741
742#endif /* RADAR_ACCUMULATOR */
743
744// Rack
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:430
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:666
Logger & note(const TT &... args)
For top-level information.
Definition Log.h:489
Logger & special(const TT &... args)
Other useful information.
Definition Log.h:531
Logger & fail(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:453
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:476
Logger & error(const TT &... args)
Echoes.
Definition Log.h:416
Logger & accept(const TT &... args)
Some input has been accepted, for example by a syntax.
Definition Log.h:582
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition Log.h:511
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:676
static void updateValues(M &dst, const std::map< std::string, S > &src)
Definition SmartMapTools.h:205
static const std::type_info & getTypeInfo(char t)
Returns the base type associated with a character key.
Definition Type.h:134
double & scale
Multiplicative coefficient \i a in: y = ax + b.
Definition ValueScaling.h:68
double & offset
Additive coefficient \i b in: y = ax + b.
Definition ValueScaling.h:71
Function for accumulating data: maximum, average, weighted average etc.
Definition AccumulationMethods.h:65
Definition Accumulator.h:76
static bool isSpecific(FieldType field)
Future option to mark scaled/normalized etc.
Definition Accumulator.h:114
void extractField(char field, const AccumulationConverter &converter, Image &dst, const drain::Rectangle< int > &crop) const
Extracts the accumulated quantity or secondary quantities like weight and standard deviation.
Definition Accumulator.h:245
FieldType
Definition Accumulator.h:84
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition Image.h:193
Converts ODIM encoded data (with markers) to natural values and backwards.
Definition DataCoder.h:61
Tool for selecting datasets based on paths, quantities and min/max elevations.
Definition DataSelector.h:112
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition Data.h:1215
Structure for data storage type, scaling and marker codes. Does not contain quantity.
Definition EncodingODIM.h:75
void setType(const std::type_info &type)
Complete with setTypeDefaults()
Definition EncodingODIM.h:187
std::string type
This is non-standard (not in ODIM), but a practical means of handling storage type of datasets.
Definition EncodingODIM.h:152
static const group_t QUALITY
Special group on first or second level, /quality + digit , used for storing quality data.
Definition ODIMPath.h:115
static const group_t DATA
Second level group, /data + digit .
Definition ODIMPath.h:109
ODIM metadata (quantity, gain, offset, undetect, nodata, date, time)
Definition ODIM.h:79
std::string quantity
dataX/what (obligatory)
Definition ODIM.h:181
Essential class for storing radar data.
Definition Data.h:300
Base class providing quality support for Dataand DataSet
Definition Data.h:1034
Registry for regular quantities appearing in weather radar.
Definition QuantityMap.h:67
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
bool hasQuantity(const std::string &key) const
Checks if an exact match or a variant, is found.
Definition QuantityMap.h:119
Todo: consider non-template class:
Definition RadarAccumulator.h:63
size_t counter
Book-keeping for new data. Finally, in extraction phase, added to odim.ACCnum .
Definition RadarAccumulator.h:95
DataSelector dataSelector
Input data selector.
Definition RadarAccumulator.h:80
double defaultQuality
If source data has no quality field, this value is applied for (detected) data.
Definition RadarAccumulator.h:89
Data array for creating composites and accumulated polar products (Surface rain fall or cluttermaps)
Definition RadarAccumulator.h:122
OD odim
For storing the scaling and encoding of (1st) input or user-defined values. Also for bookkeeping of d...
Definition RadarAccumulator.h:185
void addData(const pdata_src_t &srcData, const pdata_src_t &srcQuality, double weight, int i0, int j0)
Adds data that is in the same coordinate system as the accumulator. Weighted with quality.
Definition RadarAccumulator.h:267
void extractOLD(const OD &odimOut, DataSet< DstType< OD > > &dstProduct, const std::string &fields, const drain::Rectangle< int > &crop={0, 0, 0, 0}) const
Definition RadarAccumulator.h:567
RadarAccumulator()
Default constructor.
Definition RadarAccumulator.h:133
void addData(const pdata_src_t &srcData, const pdata_src_t &srcQuality, const pdata_src_t &srcCount)
Adds data that is in the same coordinate system as the accumulator.
Definition RadarAccumulator.h:302
bool checkCompositingMethod(const ODIM &dataODIM)
Warns if data scaling involves risks in using WAVG (weighted averaging)
Definition RadarAccumulator.h:215
PlainData< SrcType< OD const > > pdata_src_t
Input data type.
Definition RadarAccumulator.h:127
pdata_dst_t & extract(DataSet< DstType< OD > > &dstProduct, field_t field=field_t::DATA, const std::string &encoding="C", const drain::Rectangle< int > &cropArea={0, 0})
Definition RadarAccumulator.h:373
void setTargetEncoding(const std::string &encoding)
Not critical. If set, needed to warn if input data does not match the expected / potential targetEnco...
Definition RadarAccumulator.h:225
Definition DataSelector.cpp:44
QuantityMap & getQuantityMap()
Definition QuantityMap.cpp:279
Rectange defined through lower left and upper right coordinates.
Definition Rectangle.h:65
bool empty() const
Return true if the area is zero.
Definition Rectangle.h:111
Writable data type.
Definition Data.h:120