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>drain::image::Accumulator::FieldType
38#include <drain/image/Accumulator.h> // ostream field...
39#include <drain/image/AccumulatorGeo.h>
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<LOG_DEBUG>("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 //mout.debug("extracting field '", field, "' = ", static_cast<int>(field), " #", drain::EnumDict<drain::image::Accumulator::FieldType>::dict.getKey(field));
412 mout.debug("extracting field '", field, "' (", static_cast<int>(field), ")");
413
414 {
415
416 /*
417 if (odimData.quantity.empty()){
418 odimData.quantity = "UNKNOWN"; // ok; for example --cPlotFile carries no information on quantity
419 mout.note("quantity=", odimData.quantity);
420 }
421 */
422 mout.debug(DRAIN_LOG(dataCoder));
423 mout.debug2(DRAIN_LOG(dataCoder.dataODIM));
424 mout.debug2(DRAIN_LOG(dataCoder.qualityODIM));
425
427
428 // Note: encoding is used only for DATA to avoid ambiguous setting for multiple request of fields: DATA,WEIGHT,COUNT, ...
429 if (field == field_t::DATA){
430
431 //pdata_dst_t & dstData = dstProduct.getData(this->odim.quantity);
432
433 // TODO: clean confusing mixture of dataCoder.dataODIM <==> odimData
434
435
436 // Update 1/2: from initial values to this "instantaneous" extraction
437 drain::SmartMapTools::updateValues(odimData, this->odim); // lazy (qualityData does not need)
438
439 mout.debug("extracting DATA/" , field, " [", odimData.quantity, ']');
440
441 if (!encoding.empty()){
442 mout.accept("User-defined encoding for data [", odimData.quantity, "]: ", encoding);
443 //odimData.completeEncoding( encoding);
444 odimData.completeEncoding(encoding);
445 }
446 else if (!getTargetEncoding().empty()){
447 mout.ok<LOG_NOTICE>("Using initial/default encoding for data [", odimData.quantity, "]: ", getTargetEncoding());
448 // odimData.completeEncoding( getTargetEncoding());
449 odimData.completeEncoding(getTargetEncoding());
450 }
451
452 if (odimData.quantity.empty()){
453 mout.error("unspecified quantity");
454 }
455
456 pdata_dst_t & dstData = dstProduct.getData(odimData.quantity);
457
458 // Update 2/2: copy "instantaneous", maybe adjusted encoding to retrieved data
459 extractFinally(*this, field, odimData, dataCoder, dstData.odim, dstData.data, cropArea);
460 return dstData;
461 /*
462 drain::SmartMapTools::updateValues(dstData.odim, odimData);
463
464 if (dataCoder.dataODIM.isSet()){
465 dstData.data.setType(odimData.type);
466 mout.debug3("dstData: " , dstData );
467 this->Accumulator::extractField(field, dataCoder, dstData.data, cropArea);
468 return dstData;
469 }
470 else {
471 // Note: this is also checked by Accumulator, but better diagnostics (ODIM) here:
472 mout.error("Target encoding unset: gain=", dataCoder.dataODIM.scaling.scale, ", type=", dataCoder.dataODIM.type);
473 return dstData;
474 }
475 */
476
477 }
478 else {
479
480 switch (field){
481 case field_t::WEIGHT_DS:
482 case field_t::WEIGHT:
483 odimQuality.quantity = "QIND";
484 break;
485 case field_t::COUNT_DS:
486 case field_t::COUNT:
487 odimQuality.quantity = "COUNT";
488 break;
489 case field_t::DEVIATION:
490 odimQuality.quantity = this->odim.quantity + "DEV";
491 break;
492 default:
493 mout.error("Unsupported field marker: ", field, "='", fieldChar, "'");
494 //mout.error("Unsupported field marker: ", FieldFlagger::getKeysNEW2(field));
495 }
496
497 mout.debug("extracting QUALITY/" , field, " [", odimQuality.quantity, ']');
498
499 if (qm.hasQuantity(odimQuality.quantity)){
500 qm.setQuantityDefaults(odimQuality, odimQuality.quantity, odimQuality.type);
501 mout.accept<LOG_DEBUG>("found quantityConf[", odimQuality.quantity, "], type=", odimQuality.type);
502 mout.special<LOG_DEBUG>("Quality: ", EncodingODIM(odimQuality));
503 mout.special<LOG_DEBUG>("Quality: ", odimQuality);
504 }
505 else if (!encoding.empty()){
506 mout.accept<LOG_INFO>("User-defined encoding for quality [", odimQuality.quantity, "]: ", encoding);
507 odimQuality.completeEncoding(encoding);
508 mout.debug("User-defined encoding for QUALITY: -> ", odimQuality);
509 }
510 else {
511 // mout.experimental("No predefined scaling for ", odimQuality.quantity);
512 /*
513 const std::type_info & t = drain::Type::getTypeInfo(odimQuality.type);
514 odimQuality.scaling.scale *= 20.0; // ?
515 odimQuality.scaling.offset = round(drain::Type::call<drain::typeMin, double>(t) + drain::Type::call<drain::typeMax, double>(t))/2.0;
516 if (encoding.empty()){
517 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using somewhat arbitrary scaling:" );
518 mout.special("Quality: ", EncodingODIM(odimQuality));
519 }
520 */
521 odimQuality.setType(typeid(float));
522 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using float" );
523 mout.special("Quality: ", EncodingODIM(odimQuality));
524
525 }
526 // else auto-scale?
527
528
529 typedef QualityDataSupport<DstType<OD> > q_support_t;
530 q_support_t & qualityOwner = Accumulator::isSpecific(field) ? (q_support_t &) dstProduct.getData(odimData.quantity) : (q_support_t &) dstProduct;
531 pdata_dst_t & dstQuality = qualityOwner.getQualityData(odimQuality.quantity);
532
533
534 // NOTE similarity... but fct still would need separating (dataCoder, odimData, odimQuality, odimNow, field, crop)
535 extractFinally(*this, field, odimQuality, dataCoder, dstQuality.odim, dstQuality.data, cropArea);
536 return dstQuality;
537 /*
538 drain::SmartMapTools::updateValues(dstQuality.odim, odimQuality);
539 // if (dataCoder.squalityODIM.isSet()){
540 if (dstQuality.odim.isSet()){
541 // dstQuality.data.setType(odimData.type); // <- this was probably wrong
542 dstQuality.data.setType(dstQuality.odim.type); // <- this was probably wrong
543 mout.debug3("dstData: " , dstQuality );
544 this->Accumulator::extractField(fieldChar, dataCoder, dstQuality.data, cropArea);
545 return dstQuality;
546 }
547 else {
548 // Note: this is also checked by Accumulator, but better diagnostics (ODIM) here:
549 mout.error("Target encoding unset: gain=", dstQuality.odim.scaling.scale, ", type=", dstQuality.odim.type);
550 //mout.error("Target encoding unset: gain=", dataCoder.qualityODIM.scaling.scale, ", type=", dataCoder.qualityODIM.type);
551 return dstQuality;
552 }
553 */
554
555 }
556
557 // mout.debug("updating local tree attributes");
558
559 }
560
561
562 // mout.debug("updating local tree attributes" );
563 // mout.debug("finished" );
564
565}
566
567// TODO: remove this (use the new ones)
568template <class AC, class OD>
569void RadarAccumulator<AC,OD>::extractOLD(const OD & odimOut, DataSet<DstType<OD> > & dstProduct,
570 const std::string & fields, const drain::Rectangle<int> & crop) const {
571 // , const drain::Rectangle<double> & bbox) const {
572
573 drain::Logger mout(__FILE__, __FUNCTION__);
574
575 const std::type_info & t = drain::Type::getTypeInfo(odimOut.type);
576
577 typedef enum {DATA,QUALITY} datatype;
578
579 OD odimData;
580 odimData = odimOut;
581 odimData.scaling.scale = 0.0; // ?
582
583 const QuantityMap & qm = getQuantityMap();
584
585 // Determines if quality is stored in
586 // /dataset1/quality1/
587 // or
588 // /dataset1/data1/quality1/
589 //
590 bool DATA_SPECIFIC_QUALITY = false;
591
592 // Consider redesign, with a map of objects {quantity, type,}
593 for (size_t i = 0; i < fields.length(); ++i) {
594
595 ODIM odimQuality;
596 odimQuality.quantity = "QIND";
597
598 // std::stringstream dataPath;
599
600 datatype type = DATA;
601 char field = fields.at(i);
602 switch (field) {
603 case '/':
604 DATA_SPECIFIC_QUALITY = true;
605 continue;
606 break; // unneeded?
607 case 'm': // ???
608 case 'D':
609 case 'p': // ???
610 mout.warn() << "non-standard layer code; use 'd' for 'data' instead" << mout.endl;
611 // no break
612 case 'd':
613 type = DATA;
614 odimData = odimOut; // consider update
615 qm.setQuantityDefaults(odimQuality, "QIND"); // ?
616 odimQuality.quantity = "QIND";
617 break;
618 case 'c':
619 type = QUALITY;
620 qm.setQuantityDefaults(odimQuality, "COUNT");
621 odimQuality.quantity = "COUNT";
622 break;
623 case 'C':
624 type = QUALITY;
625 qm.setQuantityDefaults(odimQuality, "COUNT", "d");
626 odimQuality.quantity = "COUNT";
627 break;
628 // case 'q': // consider
629 case 'w':
630 // no break
631 type = QUALITY;
632 odimData = odimOut; // (Because converter needs both data and weight to encode weight?)
633 qm.setQuantityDefaults(odimQuality, "QIND", "C");
634 odimQuality.quantity = "QIND";
635 //odimQuality.undetect = 256;
636 //odimQuality.nodata = -1; // this is good, because otherwise nearly-undetectValue-quality CAPPI areas become no-data.
637 break;
638 case 'W':
639 mout.warn("experimental: quality [QIND] type copied from data [" , odimOut.quantity , ']' );
640 // no break
641 type = QUALITY;
642 odimData = odimOut; // (Because converted needs both data and weight to encode weight?)
643 qm.setQuantityDefaults(odimQuality, "QIND", odimOut.type);
644 odimQuality.quantity = "QIND";
645 //odimQuality.undetect = 256;
646 //odimQuality.nodata = -1; // this is good, because otherwise nearly-undetectValue-quality CAPPI areas become no-data.
647 break;
648 case 's':
649 type = QUALITY;
650 odimQuality = odimOut;
651 odimQuality.quantity += "DEV";
652 if (qm.hasQuantity(odimQuality.quantity)){
653 qm.setQuantityDefaults(odimQuality, odimQuality.quantity, odimQuality.type);
654 mout.accept<LOG_NOTICE>("found quantyConf[", odimQuality.quantity, "], type=", odimQuality.type);
655 //mout.special("Quality: ", EncodingODIM(odimQuality));
656 mout.special("Quality: ", EncodingODIM(odimQuality));
657 mout.special("Quality: ", odimQuality);
658 }
659 else {
660 odimQuality.scaling.scale *= 20.0; // ?
661 //const std::type_info & t = Type::getType(odimFinal.type);
662 odimQuality.scaling.offset = round(drain::Type::call<drain::typeMin, double>(t) + drain::Type::call<drain::typeMax, double>(t))/2.0;
663 //odimQuality.offset = round(drain::Type::call<drain::typeMax,double>(t) + drain::Type::getMin<double>(t))/2.0; // same as data!
664 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using somewhat arbitary scaling:" );
665 mout.special("Quality: ", EncodingODIM(odimQuality));
666 }
667 break;
668 default:
669 mout.error("Unsupported field code: '", field, "'");
670 break;
671 }
672
673 mout.debug("extracting field ", field);
674
675 if (!crop.empty()){
676 mout.experimental("Applying cropping: bbox=", crop, " [pix]");
677 }
678
679 if (type == DATA){
680 mout.debug("target: " , EncodingODIM(odimData) );
681 }
682 else if (type == QUALITY){
683 mout.debug("target: " , EncodingODIM(odimQuality) );
684 }
685
686 if (odimData.quantity.empty()){
687 odimData.quantity = "UNKNOWN"; // ok; for example --cPlotFile carries no information on quantity
688 mout.note("quantity=", odimData.quantity);
689 }
690
691 //PlainData<DstType<OD> >
692 mout.debug("searching dstData... DATA=", (type == DATA));
693 //pdata_dst_t & dstData = (type == DATA) ? dstProduct.getData(odimFinal.quantity) : dstProduct.getQualityData(odimQuality.quantity);
694 //mout .debug3() << "dstData: " << dstData << mout.endl;
695
696 //DataDst dstData(dataGroup); // FIXME "qualityN" instead of dataN creates: /dataset1/qualityN/quality1/data
697 //mout.warn("odimFinal: " , odimFinal );
698 mout.debug("odimData: " , EncodingODIM(odimData) );
699 DataCoder dataCoder(odimData, odimQuality); // (will use only either odim!)
700 mout.debug("dataCoder: ", dataCoder);
701 mout.debug2("dataCoder: data: ", dataCoder.dataODIM);
702 mout.debug2("dataCoder: qind: ", dataCoder.qualityODIM);
703
704 if (!crop.empty()){
705 mout.unimplemented("crop ", crop, ", dstData.data resize + Accumulator::extractField ");
706 }
707
708 if (type == DATA){
709 mout.debug("DATA/" , field, " [", odimData.quantity, ']');
710 //mout.warn(dstData.odim );
711 pdata_dst_t & dstData = dstProduct.getData(odimData.quantity);
712 dstData.odim.importMap(odimData);
713 dstData.data.setType(odimData.type);
714 mout.debug3("dstData: " , dstData );
715 //mout.debug("quantity=" , dstData.odim.quantity );
716 this->Accumulator::extractField(field, dataCoder, dstData.data, crop);
717 }
718 else {
719 mout.debug("QUALITY/" , field , " [", odimQuality.quantity, ']');
720 //pdata_dst_t & dstData = dstProduct.getData(odimFinal.quantity);
721 typedef QualityDataSupport<DstType<OD> > q_data_t;
722 q_data_t & qualityOwner = (DATA_SPECIFIC_QUALITY) ? (q_data_t &) dstProduct.getData(odimData.quantity) : (q_data_t &) dstProduct;
723 pdata_dst_t & dstData = qualityOwner.getQualityData(odimQuality.quantity);
724 dstData.odim.updateFromMap(odimQuality);
725 mout.debug3("dstData: " , dstData );
726 this->Accumulator::extractField(field, dataCoder, dstData.data, crop);
727 }
728
729
730 // mout.debug("updating local tree attributes");
731
732 }
733
734
735 // mout.debug("updating local tree attributes" );
736 // mout.debug("finished" );
737
738}
739
740
741} // rack::
742
743
744#endif /* RADAR_ACCUMULATOR */
745
746// 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:133
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:119
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:246
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:569
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