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
73 defaultQuality(base.defaultQuality), counter(base.counter){};
74
76 const ODIM &srcODIM, const DataCoder & dataCoder,
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 */
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
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
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.");
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
283
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>
303
305 // mout.info("Quality data available with input; using quality as weights in compositing.");
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>
352void RadarAccumulator<AC,OD>::extract(DataSet<DstType<OD> > & dstProduct, const drain::image::Accumulator::FieldList & fields, const std::string & encoding, const drain::Rectangle<int> & cropArea) {
353
355
357
358 pdata_dst_t & dstData = extract(dstProduct, field, encoding, cropArea);
359
360 if (ODIM::versionFlagger.isSet(ODIM::RACK_EXTENSIONS) && !legend.empty()){
361 mout.experimental("Copying (moving) legend for ", field);
362 dstData.getWhat()["legend"] = drain::sprinter(legend, "|", ",", ":").str();
363 legend.clear();
364 }
365 }
366
367
368}
369
370
371template <class AC, class OD>
373 const std::string & encoding, const drain::Rectangle<int> & cropArea){
374
376
377 mout.debug("extracting FIELD: ", field);
378
379 char fieldChar = (char)(((int)field)&127);
380 if (fieldChar != drain::image::Accumulator::getFieldChar(field)){
381 mout.fail("program error: ", field, '=', fieldChar, "!=", drain::image::Accumulator::getFieldChar(field));
382 }
383
384 //const std::type_info & t = drain::Type::getTypeInfo('C'); // drain::Type::getTypeInfo(odimOut.type);
385 if (!cropArea.empty()){
386 mout.note("Cropping ", cropArea.getWidth(), "x", cropArea.getHeight(), " from original composite ", this->accArray.getGeometry()); // this->getFrameWidth(), 'x', this->getFrameHeight());
387 mout.info("Cropping window: (", cropArea.lowerLeft, ") (", cropArea.upperRight, ") from original composite ", this->accArray.getGeometry()); // this->getFrameWidth(), 'x', this->getFrameHeight());
388 }
389
390 const QuantityMap & qm = getQuantityMap();
391
397 //bool QUANTITY_SPECIFIC_QUALITY = false;
398 //mout.experimental<LOG_NOTICE>("EncodingODIM THIS = ", this->odim);
399
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;
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::Enum<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_GLOBAL:
482 case field_t::WEIGHT:
483 odimQuality.quantity = "QIND";
484 break;
485 case field_t::COUNT_GLOBAL:
486 case field_t::COUNT:
487 odimQuality.quantity = "COUNT";
488 break;
489 case field_t::DEVIATION:
490 odimQuality.quantity = this->odim.quantity + "DEV";
491 odimQuality.type = "f";
492 break;
493 default:
494 mout.error("Unsupported field marker: ", field, "='", fieldChar, "'");
495 //mout.error("Unsupported field marker: ", FieldFlagger::getKeysNEW2(field));
496 }
497
498 mout.debug("extracting QUALITY/" , field, " [", odimQuality.quantity, ']');
499
500 if (qm.hasQuantity(odimQuality.quantity)){
501 // NOT tested, consider DEV mout.revised("Storage type for quality: using qualityConf default");
502 // qm.setQuantityDefaults(odimQuality, odimQuality.quantity);
503 qm.setQuantityDefaults(odimQuality, odimQuality.quantity, odimQuality.type);
504 mout.accept<LOG_DEBUG>("found quantityConf[", odimQuality.quantity, "], type=", odimQuality.type);
505 mout.special<LOG_DEBUG>("Quality: ", EncodingODIM(odimQuality));
506 mout.special<LOG_DEBUG>("Quality: ", odimQuality);
507 }
508 else if (!encoding.empty()){
509 mout.accept<LOG_INFO>("User-defined encoding for quality [", odimQuality.quantity, "]: ", encoding);
510 odimQuality.completeEncoding(encoding);
511 mout.debug("User-defined encoding for QUALITY: -> ", odimQuality);
512 }
513 else {
514 // mout.experimental("No predefined scaling for ", odimQuality.quantity);
515 /*
516 const std::type_info & t = drain::Type::getTypeInfo(odimQuality.type);
517 odimQuality.scaling.scale *= 20.0; // ?
518 odimQuality.scaling.offset = round(drain::Type::call<drain::typeMin, double>(t) + drain::Type::call<drain::typeMax, double>(t))/2.0;
519 if (encoding.empty()){
520 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using somewhat arbitrary scaling:" );
521 mout.special("Quality: ", EncodingODIM(odimQuality));
522 }
523 */
524 odimQuality.setType(typeid(float));
525 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using float" );
526 mout.special("Quality: ", EncodingODIM(odimQuality));
527
528 }
529 // else auto-scale?
530
532
533 mout.attention(DRAIN_LOG(field), DRAIN_LOG(QUANTITY_SPECIFIC_QUALITY));
534 //mout.attention(DRAIN_LOG(QUANTITY_SPECIFIC_QUALITY));
535
539
540
541 // NOTE similarity... but fct still would need separating (dataCoder, odimData, odimQuality, odimNow, field, crop)
542 extractFinally(*this, field, odimQuality, dataCoder, dstQuality.odim, dstQuality.data, cropArea);
543 return dstQuality;
544 /*
545 drain::SmartMapTools::updateValues(dstQuality.odim, odimQuality);
546 // if (dataCoder.squalityODIM.isSet()){
547 if (dstQuality.odim.isSet()){
548 // dstQuality.data.setType(odimData.type); // <- this was probably wrong
549 dstQuality.data.setType(dstQuality.odim.type); // <- this was probably wrong
550 mout.debug3("dstData: " , dstQuality );
551 this->Accumulator::extractField(fieldChar, dataCoder, dstQuality.data, cropArea);
552 return dstQuality;
553 }
554 else {
555 // Note: this is also checked by Accumulator, but better diagnostics (ODIM) here:
556 mout.error("Target encoding unset: gain=", dstQuality.odim.scaling.scale, ", type=", dstQuality.odim.type);
557 //mout.error("Target encoding unset: gain=", dataCoder.qualityODIM.scaling.scale, ", type=", dataCoder.qualityODIM.type);
558 return dstQuality;
559 }
560 */
561
562 }
563
564 // mout.debug("updating local tree attributes");
565
566 }
567
568
569 // mout.debug("updating local tree attributes" );
570 // mout.debug("finished" );
571
572}
573
574// TODO: remove this (use the new ones)
575template <class AC, class OD>
577 const std::string & fields, const drain::Rectangle<int> & crop) const {
578 // , const drain::Rectangle<double> & bbox) const {
579
581
582 const std::type_info & t = drain::Type::getTypeInfo(odimOut.type);
583
584 typedef enum {DATA,QUALITY} datatype;
585
586 OD odimData;
587 odimData = odimOut;
588 odimData.scaling.scale = 0.0; // ?
589
590 const QuantityMap & qm = getQuantityMap();
591
592 // Determines if quality is stored in
593 // /dataset1/quality1/
594 // or
595 // /dataset1/data1/quality1/
596 //
597 bool QUANTITY_SPECIFIC_QUALITY = false;
598
599 // Consider redesign, with a map of objects {quantity, type,}
600 for (size_t i = 0; i < fields.length(); ++i) {
601
603 odimQuality.quantity = "QIND";
604
605 // std::stringstream dataPath;
606
607 datatype type = DATA;
608 char field = fields.at(i);
609 switch (field) {
610 case '/':
612 continue;
613 break; // unneeded?
614 case 'm': // ???
615 case 'D':
616 case 'p': // ???
617 mout.warn() << "non-standard layer code; use 'd' for 'data' instead" << mout.endl;
618 // no break TODO: CHECK
619 case 'd':
620 type = DATA;
621 odimData = odimOut; // consider update
622 qm.setQuantityDefaults(odimQuality, "QIND"); // ?
623 odimQuality.quantity = "QIND";
624 break;
625 case 'c':
626 type = QUALITY;
627 qm.setQuantityDefaults(odimQuality, "COUNT");
628 odimQuality.quantity = "COUNT";
629 break;
630 case 'C':
631 type = QUALITY;
632 qm.setQuantityDefaults(odimQuality, "COUNT", "d");
633 odimQuality.quantity = "COUNT";
634 break;
635 // case 'q': // consider
636 case 'w':
637 // no break
638 type = QUALITY;
639 odimData = odimOut; // (Because converter needs both data and weight to encode weight?)
640 qm.setQuantityDefaults(odimQuality, "QIND", "C");
641 odimQuality.quantity = "QIND";
642 //odimQuality.undetect = 256;
643 //odimQuality.nodata = -1; // this is good, because otherwise nearly-undetectValue-quality CAPPI areas become no-data.
644 break;
645 case 'W':
646 mout.warn("experimental: quality [QIND] type copied from data [" , odimOut.quantity , ']' );
647 // no break
648 type = QUALITY;
649 odimData = odimOut; // (Because converted needs both data and weight to encode weight?)
650 qm.setQuantityDefaults(odimQuality, "QIND", odimOut.type);
651 odimQuality.quantity = "QIND";
652 //odimQuality.undetect = 256;
653 //odimQuality.nodata = -1; // this is good, because otherwise nearly-undetectValue-quality CAPPI areas become no-data.
654 break;
655 case 's':
656 type = QUALITY;
657 odimQuality = odimOut;
658 odimQuality.quantity += "DEV";
659 if (qm.hasQuantity(odimQuality.quantity)){
660 qm.setQuantityDefaults(odimQuality, odimQuality.quantity, odimQuality.type);
661 mout.accept<LOG_NOTICE>("found quantyConf[", odimQuality.quantity, "], type=", odimQuality.type);
662 //mout.special("Quality: ", EncodingODIM(odimQuality));
663 mout.special("Quality: ", EncodingODIM(odimQuality));
664 mout.special("Quality: ", odimQuality);
665 }
666 else {
667 odimQuality.scaling.scale *= 20.0; // ?
668 //const std::type_info & t = Type::getType(odimFinal.type);
669 odimQuality.scaling.offset = round(drain::Type::call<drain::typeMin, double>(t) + drain::Type::call<drain::typeMax, double>(t))/2.0;
670 //odimQuality.offset = round(drain::Type::call<drain::typeMax,double>(t) + drain::Type::getMin<double>(t))/2.0; // same as data!
671 mout.warn("quantyConf[" , odimQuality.quantity , "] not found, using somewhat arbitary scaling:" );
672 mout.special("Quality: ", EncodingODIM(odimQuality));
673 }
674 break;
675 default:
676 mout.error("Unsupported field code: '", field, "'");
677 break;
678 }
679
680 mout.debug("extracting field ", field);
681
682 if (!crop.empty()){
683 mout.experimental("Applying cropping: bbox=", crop, " [pix]");
684 }
685
686 if (type == DATA){
687 mout.debug("target: " , EncodingODIM(odimData) );
688 }
689 else if (type == QUALITY){
690 mout.debug("target: " , EncodingODIM(odimQuality) );
691 }
692
693 if (odimData.quantity.empty()){
694 odimData.quantity = "UNKNOWN"; // ok; for example --cPlotFile carries no information on quantity
695 mout.note("quantity=", odimData.quantity);
696 }
697
698 //PlainData<DstType<OD> >
699 mout.debug("searching dstData... DATA=", (type == DATA));
700 //pdata_dst_t & dstData = (type == DATA) ? dstProduct.getData(odimFinal.quantity) : dstProduct.getQualityData(odimQuality.quantity);
701 //mout .debug3() << "dstData: " << dstData << mout.endl;
702
703 //DataDst dstData(dataGroup); // FIXME "qualityN" instead of dataN creates: /dataset1/qualityN/quality1/data
704 //mout.warn("odimFinal: " , odimFinal );
705 mout.debug("odimData: " , EncodingODIM(odimData) );
706 DataCoder dataCoder(odimData, odimQuality); // (will use only either odim!)
707 mout.debug("dataCoder: ", dataCoder);
708 mout.debug2("dataCoder: data: ", dataCoder.dataODIM);
709 mout.debug2("dataCoder: qind: ", dataCoder.qualityODIM);
710
711 if (!crop.empty()){
712 mout.unimplemented("crop ", crop, ", dstData.data resize + Accumulator::extractField ");
713 }
714
715 if (type == DATA){
716 mout.debug("DATA/" , field, " [", odimData.quantity, ']');
717 //mout.warn(dstData.odim );
718 pdata_dst_t & dstData = dstProduct.getData(odimData.quantity);
719 dstData.odim.importMap(odimData);
720 dstData.data.setType(odimData.type);
721 mout.debug3("dstData: " , dstData );
722 //mout.debug("quantity=" , dstData.odim.quantity );
723 this->Accumulator::extractField(field, dataCoder, dstData.data, crop);
724 }
725 else {
726 mout.debug("QUALITY/" , field , " [", odimQuality.quantity, ']');
727 //pdata_dst_t & dstData = dstProduct.getData(odimFinal.quantity);
731 dstData.odim.updateFromMap(odimQuality);
732 mout.debug3("dstData: " , dstData );
733 this->Accumulator::extractField(field, dataCoder, dstData.data, crop);
734 }
735
736
737 // mout.debug("updating local tree attributes");
738
739 }
740
741
742 // mout.debug("updating local tree attributes" );
743 // mout.debug("finished" );
744
745}
746
747
748} // rack::
749
750
751#endif /* RADAR_ACCUMULATOR */
752
753// Rack
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
static void updateValues(M &dst, const std::map< std::string, S > &src)
Definition MapTools.h:227
static const std::type_info & getTypeInfo(char t)
Returns the base type associated with a character key.
Definition Type.h:131
Function for accumulating data: maximum, average, weighted average etc.
Definition AccumulationMethods.h:66
Definition Accumulator.h:76
static bool isSpecific(FieldType field)
Future option to mark scaled/normalized etc.
Definition Accumulator.h:120
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:247
FieldType
Definition Accumulator.h:84
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition Image.h:183
Converts ODIM encoded data (with markers) to natural values and backwards.
Definition DataCoder.h:58
Tool for selecting datasets based on paths, quantities and min/max elevations.
Definition DataSelector.h:106
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition Data.h:1293
Structure for data storage type, scaling and marker codes. Does not contain quantity.
Definition EncodingODIM.h:70
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
Essential class for storing radar data.
Definition Data.h:311
const plaindata_t & getQualityData(const std::string &quantity="QIND") const
Finds associated quality data - maybe empty and unscaled.
Definition Data.h:1137
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:210
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:576
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:372
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 AltitudeOp.cpp:42
QuantityMap & getQuantityMap()
Definition QuantityMap.cpp:282
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