Loading...
Searching...
No Matches
Data.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// Thanks to: Mikael Kilpeläinen
32
33#ifndef DATA_H_
34#define DATA_H_
35
36#include <data/QuantitySelector.h>
37#include <list>
38#include <map>
39
40#include <drain/util/ReferenceMap.h>
41
42#include "DataSelector.h"
43#include "DataTools.h"
44#include "PolarODIM.h"
45#include "CartesianODIM.h"
46#include "VerticalODIM.h"
47
48
49using namespace drain::image;
50
51namespace rack {
52
76
82template <typename T, typename TI, typename D>
83struct DataType {
84 typedef T tree_t;
85 typedef TI tree_iter_t;
86 typedef D image_t;
87};
88
89
90/*
91template <class T, size_t N>
92struct TypeName<UniTuple<T,N> > {
93
94 static const std::string & str(){
95 static std::string name = drain::StringBuilder<>("UniTuple<", drain::TypeName<T>::str(), ',', N, ">");
96 return name;
97 }
98
99};
100*/
101
103
106template <typename M = PolarODIM const>
107struct SrcType : public DataType<Hi5Tree const, Hi5Tree::const_iterator, Image const> {
108 typedef M odim_t;
109};
110
111
113
116template <typename M = PolarODIM>
117struct DstType : public DataType<Hi5Tree, Hi5Tree::iterator, Image> {
118 typedef M odim_t;
119};
120
123
126
129
130
131typedef DstType<ODIM> BasicDst;
132
135
138
141
144
145
146
148
154template <typename DT>
156public:
157
158 typedef DT datatype_t;
159 typedef typename DT::tree_t tree_t;
160 typedef typename DT::tree_iter_t tree_iter_t;
161
162 inline
163 const drain::VariableMap & getWhat() const {
165 }
166
167 inline
168 drain::VariableMap & getWhat() {
170 }
171
172 inline
173 const drain::VariableMap & getWhere() const {
175 }
176
177 inline
178 drain::VariableMap & getWhere() {
180 }
181
182
183 inline
184 const drain::VariableMap & getHow() const {
186 }
187
188 inline
189 drain::VariableMap & getHow() { // ODIMPathElem(ODIMPathElem::HOW)
191 }
192
193 // Mark this data temporary so that it will not be save by Hi5::write().
194 inline
195 void setExcluded(bool exclude = true){
196 this->tree.data.exclude = exclude;
197 };
198
199 // Mark this data temporary so that it will not be save by Hi5::write().
200 inline
201 bool isExcluded() const {
202 return this->tree.data.exclude;
203 };
204
205 //typename DT::odim_t odim;
206
207 virtual inline
208 const tree_t & getTree() const { return this->tree; };
209
210 // expected public, at least by DetectorOp::storeDebugData()
211 virtual inline
212 tree_t & getTree(){ return this->tree; } ;
213
214
215protected:
216
218 tree_t & tree;
219
220 TreeWrapper(tree_t & tree) : tree(tree){
221 };
222
223 //TreeWrapper(tree_t & tree, const odim_t & odim) tree(tree), odim(odim) {};
224 TreeWrapper(const TreeWrapper & d) : tree(d.tree){}; //, image(d.data), odim(d.odim) {};
225
226
227 ~TreeWrapper(){
228 /*
229 drain::Logger mout("TreeWrapper", __FUNCTION__);
230 if (this->tree.data.exclude){
231 mout.note("deleting (children only?)" );
232 this->tree.clear();
233 }
234 */
235 };
236
237
238 template <ODIMPathElem::group_t G>
239 const drain::VariableMap & getAttr() const {
240 return this->tree[ODIMPathElem(G)].data.attributes;
241 }
242
243 template <ODIMPathElem::group_t G>
244 drain::VariableMap & getAttr(){
245 return this->tree[ODIMPathElem(G)].data.attributes;
246 }
247
248
249};
250
251// In future, could be the interface for wrapping the whole structure?
252
254
260template <typename DT>
261class RootData : public TreeWrapper<DT> {
262
263public:
264
265 /*
266 RootData(typename DT::tree_t & tree) : TreeWrapper<DT>(tree) { // This could be good: odim(ODIMPathElem::ROOT) ... but failed with current design
267 // experimental
268 this->odim.copyFrom(tree.data.image); // <- works (only) if updateInternalAttributes() has been called?
269 };
270 */
271
272 RootData(typename DT::tree_t & tree) : TreeWrapper<DT>(tree), odim(tree.data.image) { // This could be good: odim(ODIMPathElem::ROOT) ... but failed with current design
273 // experimental
274 // this->odim.copyFrom(tree.data.image); // <- works (only) if updateInternalAttributes() has been called?
275 };
276
277 /* error
278 RootData(const typename DT::tree_t & tree) : TreeWrapper<DT>(tree) { // This could be good: odim(ODIMPathElem::ROOT) ... but failed with current design
279 // experimental
280 this->odim.copyFrom(tree.data.image); // <- works (only) if updateInternalAttributes() has been called?
281 };
282 */
283
284 virtual inline
285 ~RootData(){
286
288 mout.experimental<LOG_DEBUG>("invoking ODIM::updateH5AttributeGroups<ODIMPathElem::ROOT>()");
289 mout.experimental<LOG_DEBUG+1>("root odim: ", this->odim);
290
291 ODIM::updateH5AttributeGroups<ODIMPathElem::ROOT>(this->odim, this->tree);
292 DataTools::updateInternalAttributes(this->tree); // overrides anything?
293 };
294
295 // Metadata structure
296 typename DT::odim_t odim;
297
298};
299
300
302
310template <typename DT>
311class PlainData : public TreeWrapper<DT> {
312public:
313
314 typedef typename DT::tree_t tree_t;
315 typedef typename DT::image_t image_t;
316 typedef typename DT::odim_t odim_t;
317
318 // NEW
319 inline
320 PlainData(typename DT::tree_t & tree) :
322 data(tree[ODIMPathElem::ARRAY].data.image), // "data"
323 odim(data, data.properties.get("what:quantity",""))
324 {
325 //data.setScaling(odim.scaling.scale, odim.scaling.offset);
326 }
327
329 PlainData(typename DT::tree_t & tree, const std::string & quantity) :
331 data(tree[ODIMPathElem::ARRAY].data.image), // "data"
332 odim(data, quantity) // reads data.properties?
333 {
334 //data.setScaling(odim.scaling.scale, odim.scaling.offset);
335 }
336
338
347 template <typename DT2>
348 PlainData(const PlainData<DT2> & d) : TreeWrapper<DT>(d.getTree()),
349 data(this->tree[ODIMPathElem::ARRAY].data.image), // "data"
350 // odim(d.odim) // OLD
351 odim(data) // NEW
352 {
353 //odim.updateFromMap(d.odim); // NEW
354 //odim.updateFromCastableMap(d.odim); // NEW
355 //data.setScaling(odim.scaling.scale, odim.scaling.offset);
356 }
357
358 inline
359 ~PlainData(){
360 //drain::Logger mout("PlainData", __FUNCTION__);
361 //mout.debug2("calling updateTree2, odim: " , odim );
362 updateTree2();
363 }
364
366
369 template <class T>
370 inline
371 void setEncoding(const T & type, const std::string & values = ""){
372 //odim.type = drain::Type::getTypeChar(type);
373 this->odim.type = drain::Type::getTypeChar(drain::Type(type));
374 this->odim.setTypeDefaults(type, values);
375 data.setType(type);
376 // TODO: data.setScaling(odim.scaling); ??
377 }
378
380
383 // inline
384 void copyEncoding(const EncodingODIM & odim){
385 this->odim.copyEncoding(odim);
386 /*
387 this->odim.scaling.set(odim.scaling);
388 this->odim.nodata = odim.nodata;
389 this->odim.undetect = odim.undetect;
390 */
391 data.setType(this->odim.type);
392 data.setScaling(this->odim.scaling); // needed?
393 // PROBLEM, if Cart vs Polar: this->odim.importMap(odim);
394 }
395
396
398
401 template <class DT2>
402 inline
404 copyEncoding((const EncodingODIM &)srcData.odim);
405 // PROBLEM, if Cart vs Polar: this->odim.importMap(srcData.odim);
406 // data.setType(this->odim.type);
407 // data.setScaling(this->odim.scaling); // needed?
408 }
409
410 inline
411 void setPhysicalRange(double min, double max){
412 //data.setPhysicalScale(min, max);
413 data.setPhysicalRange(min, max, true);
414 // data.setOptimalScale();
415 this->odim.scaling.assignSequence(data.getScaling());
416 // odim.scaling.scale = data.getScaling().scale; // needed?
417 // odim.scaling.offset = data.getScaling().offset; // needed?
418 }
419
420
421
423 inline
424 void setGeometry(size_t cols, size_t rows){
425 this->odim.setGeometry(cols, rows);
426 data.setGeometry(cols, rows);
427 }
428
430 inline
432 this->odim.setGeometry(geometry.getWidth(), geometry.getHeight());
433 data.setGeometry(geometry);
434 }
435
437
440 inline
441 void setGeometry(const odim_t & odim){
442 this->odim.setGeometry(odim.area);
443 data.setGeometry(odim.area);
444 // Note:
445 this->odim.resolution = odim.resolution;
446 }
447
449
452 template <class DT2>
453 inline
455 setGeometry(srcData.odim);
456 /*
457 this->odim.setGeometry(srcData.odim.area);
458 data.setGeometry(srcData.odim.area);
459 // Note:
460 this->odim.resolution = srcData.odim.resolution;
461 */
462 }
463
465 template <class T>
466 inline
467 void initialize(const T & type, size_t cols, size_t rows){
468 setEncoding(type);
469 setGeometry(cols, rows);
470 }
471
472 template <class T>
473 inline
474 void initialize(const T & type, const drain::image::AreaGeometry & geometry){
475 setEncoding(type);
476 setGeometry(geometry);
477 }
478
479 // NEW policy.
481 inline
483 setEncoding(odim.type);
484 setGeometry(odim.area);
485 }
486
488 template <class ...T>
489 inline
490 void initializeBest(const std::type_info & type, const T & ...args){
491 odim.setType(type);
492 initializeBest(args...);
493 }
494
496 template <class ...T>
497 inline
498 void initializeBest(const std::string & type, const T & ...args){
499 odim.setType(type);
500 initializeBest(args...);
501 }
502
504 template <class ...T>
505 inline
506 void initializeBest(const drain::image::AreaGeometry & geometry, const T & ...args){
507 odim.area.set(geometry);
508 initializeBest(args...);
509 }
510
512 template <class ...T>
513 inline
514 void initializeBest(const EncodingODIM & encoding, const T & ...args){
515 odim.updateFromMap(encoding); // importMap can NOT be used because non-EncodingODIM arg will have a larger map
516 odim.scaling.physRange.set(encoding.scaling.physRange);
517 initializeBest(args...);
518 }
519
520
521 // inline
522 void setNyquist(double nyquistSpeed){
523 odim.NI = nyquistSpeed;
524 odim.setRange(-odim.NI, +odim.NI);
525 data.setScaling(odim.scaling);
526 }
527
528
529 // Data array
530 image_t & data;
531
532 // Metadata structure
533 odim_t odim; // 2023/01 considered ...raising to TreeContainer
534
535 //drain::Legend legend;
536
537 // Possibly this should be somewhere else? (Too specific here?)
539 void createSimpleQualityData(drain::image::Image & qualityImage, double dataQuality=1.0, double undetectQuality=0.5, double nodataQuality=0.0) const;
540
541 // Possibly this should be somewhere else? (Too specific here?)
543 inline
544 void createSimpleQualityData(PlainData<DT> & qualityData, double dataQuality=1.0, double undetectQuality=0.5, double nodataQuality=0.0) const { //, double dataQuality=1.0, double nodataQuality=0.0) const {
545 qualityData.setEncoding(typeid(unsigned char));
546 createSimpleQualityData(qualityData.data, dataQuality, undetectQuality, nodataQuality);
547 qualityData.odim.scaling.set(qualityData.data.getScaling());
548 //qualityData.odim.scaling.scale = qualityData.data.getScaling().scale;
549 //qualityData.odim.scaling.offset = qualityData.data.getScaling().offset;
550 }
551
553 inline
555 ODIM::updateH5AttributeGroups<ODIMPathElem::DATA>(this->odim, this->tree);
556 DataTools::updateInternalAttributes(this->tree); // Needed? The subtree is small... But for quality field perhaps.
557 }
558
559
560protected:
561
562
563};
564
568template <typename DT> // PlainData<DT> & quality
569void PlainData<DT>::createSimpleQualityData(drain::image::Image & quality, double dataQuality, double undetectQuality, double nodataQuality) const {
570
571 quality.setPhysicalRange(0.0, 1.0, true);
572
573 const drain::ValueScaling & scaling = quality.getScaling();
574
575 const bool DATA = !std::isnan(dataQuality);
576 const bool UNDETECT = !std::isnan(undetectQuality);
577 const bool NODATA = !std::isnan(nodataQuality);
578
579 // Default ie. unset values are non_signaling_NAN's, but maybe more elegant to skip calculations:
580 const double dataCode = DATA ? scaling.inv(dataQuality) : 0.0;
581 const double undetectCode = UNDETECT ? scaling.inv(undetectQuality) : 0.0;
582 const double nodataCode = NODATA ? scaling.inv(nodataQuality) : 0.0;
583
584 quality.setGeometry(data.getWidth(), data.getHeight());
585
586 Image::iterator it = data.begin();
587 Image::iterator wit = quality.begin();
588 while (it != data.end()){
589 //if ((*it != odim.nodata) && (*it != odim.undetect))
590 if (UNDETECT && (*it == this->odim.undetect))
591 *wit = undetectCode;
592 else if (NODATA && (*it == this->odim.nodata))
593 *wit = nodataCode;
594 else if (DATA)
595 *wit = dataCode;
596 ++it;
597 ++wit;
598 }
599
600 /*
601 const double d = scaling.inv(dataQuality);
602 const double nd = scaling.inv(nodataQuality);
603 const double un = scaling.inv(undetectQuality);
604
605 quality.setGeometry(data.getWidth(), data.getHeight());
606
607 Image::iterator it = data.begin();
608 Image::iterator wit = quality.begin();
609 while (it != data.end()){
610 //if ((*it != odim.nodata) && (*it != odim.undetect))
611 if (*it == odim.nodata)
612 *wit = nd;
613 else if (*it == odim.undetect)
614 *wit = un;
615 else
616 *wit = d;
617 ++it;
618 ++wit;
619 }
620 */
621
622}
623
624
625
629template <typename DT>
630inline
631std::ostream & operator<<(std::ostream & ostr, const PlainData<DT> & d){
632 ostr << d.data << ", ODIM:\t ";
633 ostr << d.odim << '\n';
634 ostr << "props: " << d.data.properties << '\n';
635 return ostr;
636}
637
638
640
652template <class DT, ODIMPathElem::group_t G>
653class DataGroup : public TreeWrapper<typename DT::datatype_t>, public std::map<std::string, DT > { // typename T::datatype_t
654public:
655
656 typedef DataGroup<DT,G> datagroup_t; // this type
657 typedef DT data_t;
658 typedef typename DT::datatype_t datatype_t;
659 typedef std::map<std::string, DT > map_t;
660
661 // Experimental. Mainly for geometry (width, height) - but also for date+time or elangle?
662 /*
663 typedef typename DT::odim_t odim_t;
664 odim_t baseODIM;
665
666
667 inline
668 void setGeometry(size_t width, size_t height){
669 baseODIM.setGeometry(width, height);
670 }
671
672 inline
673 void setGeometry(const drain::image::AreaGeometry & geometry){
674 baseODIM.setGeometry(geometry);
675 }
676 */
677 //typename DT::odim_t odim;// 2023/01 experimental
678
679
681
682 // DataGroup(typename DT::tree_t & tree, const drain::RegExp & quantityRegExp = drain::RegExp()) :
683 // TreeWrapper<typename DT::datatype_t>(tree), odim(tree.data.image) {
684 DataGroup(typename DT::tree_t & tree, const QuantitySelector & slct = QuantitySelector()) :
685 TreeWrapper<typename DT::datatype_t>(tree) { //, baseODIM(ODIMPathElem::DATASET) {
686 init(tree, *this, slct);
687 }
688 //init(tree, *this, quantityRegExp);
689
690 /*
691 DataGroup(typename DT::tree_t & tree, const drain::RegExp & quantityRegExp = drain::RegExp()) :
692 TreeWrapper<typename DT::datatype_t>(tree) {
693 init(tree, *this, quantityRegExp);
694 }
695 */
696
697 // TreeWrapper<typename DT::datatype_t>(src.tree), odim(src.tree.data.image) {
698
699 // TODO: CHECK: the std::map<std::string,DT> base (the quantity map itself) is explicitly
700 // default-constructed (empty) here, same as before; adapt() below populates it instead, but
701 // per the ALERT comment this already has a known discrepancy from a plain copy. Confirm intentional.
702 DataGroup(const datagroup_t & src) :
703 TreeWrapper<typename DT::datatype_t>(src.tree), map_t() { // , baseODIM(ODIMPathElem::DATASET){
704 adapt(src, *this); // ALERT: includes all the quantities, even thoug src contained only some of them
705 }
706
707
708 virtual
709 ~DataGroup(){
710 /*
711 drain::Logger mout("DataGroup<" + ODIMPathElem::getKey(G)+">", __FUNCTION__);
712 switch (this->size()) {
713 case 0:
714 mout.debug3("no data<n> groups" );
715 break;
716 default:
717 mout.info("several Data groups, using: " , this->begin()->first );
718 // no break;
719 case 1:
720 mout.debug("updating from 1st data: " , this->begin()->first );
721 updateTree3(this->getFirstData().odim); // tree
722 }
723 */
724 };
725
726
727 bool has(const std::string & quantity) const {
728 return (this->find(quantity) != this->end());
729 }
730
731 inline
732 const data_t & getData(const char *quantity) const {
733 return getData(std::string(quantity));
734 //return getData(quantity.c_str());
735 }
736
737
738 const data_t & getData(const std::string & quantity) const {
739
740 //drain::Logger mout(__FILE__, __FUNCTION__); //
741 drain::Logger mout(__FUNCTION__, "DataGroup{" + ODIMPathElem::getKey(G) + "}");
742
743 typename datagroup_t::const_iterator it = this->find(quantity);
744
745 if (it != this->end()){
746 mout.debug3('[' , quantity , "]\t = " , it->first );
747 return it->second;
748 }
749 else {
750 mout.debug('[' , quantity , "] not found, returning empty" );
751 return getEmpty();
752 }
753 }
754
755 inline
756 data_t & getData(const char *quantity) {
757 return getData(std::string(quantity));
758 //return getData(quantity.c_str());
759 }
760
761
762 data_t & getData(const std::string & quantity) {
763
764 //drain::Logger mout(__FILE__, __FUNCTION__); //REPL "DataGroup." + ODIMPathElem::getKey(G), __FUNCTION__);
765 drain::Logger mout(__FUNCTION__, "DataGroup{" + ODIMPathElem::getKey(G) + "}");
766
767 //mout.warn("non-const " );
768 typename datagroup_t::iterator it;
769 #pragma omp critical //(h5insert)
770 {
771 it = this->find(quantity);
772 if (it != this->end()){
773 mout.debug3("found " , it->first );
774 }
775 else {
776 //mout.note("not found, creating new data array" );
777 ODIMPathElem child(G);
778 ODIMPathTools::getNextChild(this->tree, child);
779 mout.debug3("add: " , child , " [" , quantity , ']' );
780 it = this->insert(this->begin(), typename map_t::value_type(quantity, DT(this->getTree()[child], quantity))); // WAS [path]
781 // it->second.setGeometry(baseODIM.getGeometry());
782 }
783 }
784 return it->second;
785
786 }
787
788 //const data_t& getData(const drain::RegExp & regExp) const {
789 const data_t& getData(const QuantitySelector & slct) const {
790
791 //drain::Logger mout("DataGroup." + ODIMPathElem::getKey(G)+"(RegExp) {const}", __FUNCTION__);
792 drain::Logger mout(__FUNCTION__, "(KeySelector): ", "DataGroup{" + ODIMPathElem::getKey(G)+"}");
793
794 // NEW
795 for (const drain::StringMatcher & m: slct.getList()){
796 for (const auto & entry: *this){
797 if (m.test(entry.first)){
798 mout.debug("quantity " , entry.first , " matches " , slct);
799 return entry.second;
800 }
801 }
802 }
803
804 /* OLD
805 for (typename datagroup_t::const_iterator it = this->begin(); it != this->end(); ++it){
806 if (slct.testQuantity(it->first)){
807 mout.debug("quantity " , it->first , " matches " , slct);
808 return it->second;
809 }
810 }
811 */
812
813 mout.note("no quantity matched with " , slct);
814
815 return getEmpty();
816
817 }
818
820
823 data_t & create(const std::string & quantity) { // , const std::string & templateQuantity, const std::string & encodingParams) {
824 data_t & d = getData(quantity);
825 d.setGeometry(0, 0); // in case existed already
826 //getQuantityMap().setQuantityDefaults(d, templateQuantity, encodingParams);
827 return d;
828 }
829
830
831 data_t & getFirstData() {
832
833 for (auto & entry: *this){
834 if (!entry.second.isExcluded()){
835 return entry.second;
836 }
837 }
838
839 drain::Logger(__FILE__, __LINE__, "DataGroup{" + ODIMPathElem::getKey(G)+"}:", __FUNCTION__).error("no data");
840 //mout.error("no data" );
841 return this->getData(""); // empty?
842
843 /*
844 const typename datagroup_t::iterator it = this->begin();
845
846 if (it == this->end()){
847 //drain::Logger mout("DataGroup." + ODIMPathElem::getKey(G), __FUNCTION__);
848 drain::Logger mout(__FUNCTION__, "DataGroup{" + ODIMPathElem::getKey(G)+"}");
849
850 mout.error("no data" );
851 return this->getData("");
852 }
853 else
854 return it->second;
855 */
856 }
857
858 const data_t & getFirstData() const {
859
860 for (const auto & entry: *this){
861 if (!entry.second.isExcluded()){
862 return entry.second;
863 }
864 }
865
866 drain::Logger(__FILE__, __LINE__, "DataGroup{" + ODIMPathElem::getKey(G)+"}:", __FUNCTION__).error("no data");
867 return this->getData(""); // empty?
868
869
870 //drain::Logger mout("DataGroup." + ODIMPathElem::getKey(G) + " {const}", __FUNCTION__);
871 /*
872 drain::Logger mout(__FUNCTION__, "DataGroup{" + ODIMPathElem::getKey(G)+"}");
873
874 //mout.warn("const" );
875
876 typename datagroup_t::const_iterator it = this->begin();
877
878 if (it != this->end()){
879 mout.debug2("found: " , it->first );
880 return it->second;
881 }
882 else {
883 mout.note("not found, returning empty" );
884 return getEmpty();
885 }
886 */
887
888 }
889
890
891 // experimental
892 data_t & getLastData() {
893
894 const typename datagroup_t::reverse_iterator it = this->rend();
895
896 if (it == this->rbegin()){
897 drain::Logger mout(__FUNCTION__, "DataGroup{" + ODIMPathElem::getKey(G)+"}");
898 mout.error("no data" );
899 return this->getData("");
900 }
901 else
902 return it->second;
903
904 }
905
906 // experimental
907 const data_t & getLastData() const {
908
909 drain::Logger mout(__FUNCTION__, "DataGroup{" + ODIMPathElem::getKey(G) + "}-const");
910
911 //mout.warn("const" );
912
913 typename datagroup_t::const_reverse_iterator it = this->rend();
914
915 if (it != this->rbegin()){
916 mout.debug2("found: " , it->first );
917 return it->second;
918 }
919 else {
920 mout.note("not found, returning empty" );
921 return getEmpty();
922 }
923
924
925 }
926
927
928protected:
929
930 static
931 const data_t & getEmpty() {
932 static typename DT::tree_t t;
933 static data_t empty(t);
934 return empty;
935 }
936
938
943 static
944 typename DT::tree_t & init(typename DT::tree_t & t, datagroup_t & dst, const QuantitySelector & slct = QuantitySelector()){
945 // typename DT::tree_t & init(typename DT::tree_t & t, datagroup_t & dst, const drain::RegExp & quantityRegExp = drain::RegExp()){
946
947 //drain::Logger mout("DataGroup." + ODIMPathElem::getKey(G), __FUNCTION__);
949
950 //const bool USE_REGEXP = quantityRegExp.isSet();
951 const bool USE_SELECTOR = slct.isSet();
952
953 // Number of potential groups for debug note at end
954 unsigned short counter = 0;
955
956 mout.debug3("collecting data items, selector='", slct, "'");
957 //if (USE_REGEXP)
958 // mout << ", regExp=" << quantityRegExp.toStr();
959 //mout << mout.endl;
960
961 // #pragma omp critical //(h5insert2)
962 {
963 // add UKMO
964
965 const std::string datasetQuantity = t[ODIMPathElem::WHAT].data.attributes.get("quantity", "");
966
967 //for (typename DT::tree_iter_t it=t.begin(); it!=t.end(); ++it){
968 for (auto & entry: t){
969
971 if (! (entry.first.is(G))){
972 //mout.warn("skip '" , it->first , "' \t group != " , G );
973 continue;
974 }
975
976 //const std::string dataQuantity = it->second["what"].data.attributes["quantity"];
977 //const std::string dataQuantity = it->second[ODIMPathElem::WHAT].data.attributes["quantity"];
978 const std::string dataQuantity = entry.second[ODIMPathElem::WHAT].data.attributes.get("quantity", ""); // otherways comes "null"
979
980 const std::string & quantity = !dataQuantity.empty() ? dataQuantity : datasetQuantity;
981
982 if (USE_SELECTOR){
983 ++counter; // candidate count
984 if (!slct.test(quantity)){
985 //if (!quantityRegExp.test(quantity)){
986 //if (it->second.hasChild("quality1"))
987 // mout.warn(it->first , "...rejecting, but has quality?" );
988 mout.debug3("rejected '" , entry.first , "' [" , quantity , "] !~" , slct ); // quantityRegExp.toStr()
989 continue;
990 }
991 }
992
993 /*
994 if (USE_REGEXP){
995 ++counter; // candidate count
996 if (!quantityRegExp.test(quantity)){
997 //if (it->second.hasChild("quality1"))
998 // mout.warn(it->first , "...rejecting, but has quality?" );
999 mout.debug3("rejected '" , entry.first , "' [" , quantity , "] !~" , quantityRegExp.toStr() );
1000 continue;
1001 }
1002 }
1003 */
1004
1005 mout.accept<LOG_DEBUG+2>("accept '", entry.first, "' [", quantity, ']' );
1006
1007 /*
1008 mout.warn(entry.first, " 1st -> ", entry.second[ODIMPathElem::ARRAY].data.image);
1009 mout.fail("type", drain::TypeName<DT>::get());
1010 DT(entry.second, quantity);
1011 mout.warn(entry.first, " 1bst-> ", entry.second[ODIMPathElem::ARRAY].data.image);
1012 */
1013
1014 if (quantity.empty()){
1015 //drain::Logger mout("DataSet", __FUNCTION__);
1016 mout.info("quantities dataset:'", datasetQuantity, "', data:'", dataQuantity, "'");
1017 mout.warn("undefined quantity in ", entry.first, ", using key=", entry.first );
1018 // Assign by path component "data3"
1019 dst.insert(typename map_t::value_type(entry.first, DT(entry.second, entry.first)));
1020 //associate(dst, it->first, it->second);
1021 }
1022 else {
1023 if (dst.find(quantity) != dst.end()){ // already created
1024 //drain::Logger mout("DataSet", __FUNCTION__);
1025 mout.warn("quantity '" , quantity , "' replaced same quantity at " , entry.first );
1026 }
1027 dst.insert(typename map_t::value_type(quantity, DT(entry.second, quantity)));
1028 //typename datagroup_t::reverse_iterator rit = dst.rend();
1029 //mout.warn("last '" , "' [" , quantity , '=' , rit->first , ']' , rit->second );
1030 //dst[quantity] = T(it->second);
1031 // mout.warn(entry.first, " 2nd -> ", entry.second[ODIMPathElem::ARRAY].data.image);
1032 }
1033 }
1034 } // end pragma
1035
1036 if (USE_SELECTOR)
1037 mout.debug3("matched " , dst.size() , "(out of " , counter , ") data items with selector: " , slct , '/' );
1038 //mout.debug3("matched " , dst.size() , "(out of " , counter , ") data items with RegExp=/" , quantityRegExp.toStr() , '/' );
1039 else
1040 mout.debug3("collected " , dst.size() , " data items" );
1041
1042 return t;
1043 };
1044
1045
1046 static
1047 //typename D::tree_t & adapt(typename D::tree_t & t, datagroup_t & dst, const datagroup_t & src){
1048 typename DT::tree_t & adapt(const datagroup_t & src, datagroup_t & dst){
1049
1051
1052 // drain::Logger mout("DataGroup." + ODIMPathElem::getKey(G), __FUNCTION__);
1053 // drain::Logger mout(__FILE__, __FUNCTION__);
1054
1055 if (src.empty()){
1056 mout.debug3("src empty" );
1057 return src.tree;
1058 }
1059 else {
1060 for (const auto & entry: src){
1061 dst.insert(entry);
1062 }
1063 }
1064
1065 /*
1066 for (typename datagroup_t::const_iterator it=src.begin(); it!=src.end(); ++it){
1067 //dst.insert(typename map_t::value_type(it->first, D(it->second, it->first)));
1068 //dst.insert(typename map_t::value_type(it->first, D(it->second)));
1069 dst.insert(typename map_t::value_type(it->first, it->second));
1070 }
1071 */
1072 mout.debug3("adapted ", dst.size(), " data items; ", src.begin()->first, "...");
1073
1074 //return t
1075 return src.tree;
1076 };
1077
1078
1079};
1080
1081template <class DT, ODIMPathElem::group_t G>
1082std::ostream & operator<<(std::ostream & ostr, const DataGroup<DT,G> & d){
1083 // ostr << "-- dataGroup ";
1084 char separator = 0;
1086 for (typename DataGroup<DT,G>::const_iterator it = d.begin(); it != d.end(); ++it){
1087 if (separator)
1088 ostr << separator;
1089 else {
1090 separator = ',';
1091 g.setGeometry(it->second.data.getGeometry());
1092 }
1093 ostr << it->first << '[' << drain::Type::getTypeChar(it->second.data.getType()) << ']';
1094 }
1095 ostr << " ("<< g << ")";
1096 /*
1097 ostr << d.data << ", ODIM:\t ";
1098 ostr << d.odim << '\n';
1099 ostr << "props: " << d.data.properties << '\n';
1100 */
1101 return ostr;
1102}
1103
1104
1106
1111template <typename DT>
1113
1114public:
1115
1116 typedef PlainData<DT> plaindata_t;
1117
1119
1120
1121 inline
1122 QualityDataSupport(typename plaindata_t::tree_t & tree) : quality(tree) {};
1123
1124 inline
1125 QualityDataSupport(const QualityDataSupport<DT> & qds) : quality(qds.quality) {};
1126
1127 virtual inline
1129
1131 /*
1132 * \param quantity - quality quantity, "QIND" by default.
1133 * \return - \c data[i]/quality[j] for which \c quantity=[quantity]
1134 *
1135 */
1136 inline
1137 const plaindata_t & getQualityData(const std::string & quantity = "QIND") const {
1138 return this->quality.getData(quantity);
1139 }
1140
1142 /*
1143 * \param quantity - quality quantity, "QIND" by default.
1144 * \return - \c data[i]/quality[j] for which \c quantity=[quantity]
1145 *
1146 */
1147 /*
1148 inline
1149 const plaindata_t & getQualityData(const drain::RegExp & quantityRE) const {
1150 return this->quality.getData(quantityRE);
1151 }
1152 */
1153
1154
1156 /*
1157 * \param quantity - quality quantity, "QIND" by default.
1158 * \return - \c data[i]/quality[j] for which \c quantity=[quantity]
1159 *
1160 */
1161 inline
1162 plaindata_t & getQualityData(const std::string & quantity = "QIND") {
1163 return this->quality.getData(quantity);
1164 }
1165
1166
1167 inline
1168 bool hasQuality() const {
1169 return !this->quality.empty();
1170 }
1171
1172 inline
1173 bool hasQuality(const std::string & quantity) const {
1174 return this->quality.find(quantity) != this->quality.end();
1175 }
1176
1177 inline
1178 const qualitygroup_t & getQuality() const {
1179 return this->quality;
1180 }
1181
1182 inline
1183 qualitygroup_t & getQuality(){
1184 return this->quality;
1185 }
1186
1187 /* Well, needs quantity, primarily. So best place perhaps not here.
1188 static
1189 void createSimpleQualityData(PlainData<DT> & data, drain::image::Image & qualityImage, double dataQuality=1.0, double undetectQuality=0.5, double nodataQuality=0.0) const;
1190
1191 static inline
1192 void createSimpleQualityData(PlainData<DT> & data, PlainData<DT> & qualityData, double dataQuality=1.0, double undetectQuality=0.5, double nodataQuality=0.0) const { //, double dataQuality=1.0, double nodataQuality=0.0) const {
1193 qualityData.setEncoding(typeid(unsigned char));
1194 createSimpleQualityData(qualityData.data, dataQuality, undetectQuality, nodataQuality);
1195 qualityData.odim.scaling.set(qualityData.data.getScaling());
1196 //qualityData.odim.scaling.offset = qualityData.data.getScaling().offset;
1197 }
1198 */
1199
1200protected:
1201
1202 qualitygroup_t quality;
1203
1204};
1205
1206
1207
1208/*
1209 * Data<PolarSrc> will return
1210 *
1211 * Quality field:
1212 * - NONE: reference to dummy.
1213 * - LAST: reference to last existing quality[1].
1214 * - NEXT: reference to new quality[N+1], where N is the last
1215 */
1216
1218
1223template <typename DT>
1224class Data : public PlainData<DT>, public QualityDataSupport<DT> {
1225public:
1226
1227 typedef PlainData<DT> plaindata_t;
1228
1229 Data(typename DT::tree_t & tree) : PlainData<DT>(tree), QualityDataSupport<DT>(tree) {
1230 }
1231
1232 Data(typename DT::tree_t & tree, const std::string & quantity) : PlainData<DT>(tree, quantity), QualityDataSupport<DT>(tree) {
1233 }
1234
1235 Data(const Data<DT> & d) : PlainData<DT>(d), QualityDataSupport<DT>(d) { // was: d.tree, d.tree
1236 }
1237
1238 // Data(const Hi5Tree & src, const std::string & quantity = "^DBZH$");
1239 virtual ~Data(){};
1240
1241 // Experimental
1242 void swap(Data<DT> &d){ // TODO: also for plaindata?
1243
1244 drain::Logger mout("Data<DT>", __FUNCTION__);
1245 mout.experimental("Swapping...");
1246 this->tree.swap(d.tree);
1247
1248 typename DT::odim_t odim;
1249 odim.updateFromMap(this->odim);
1250 this->odim.updateFromMap(d.odim);
1251 d.odim.updateFromMap(odim);
1252
1253 this->updateTree2();
1254 d.updateTree2();
1255 }
1256
1257protected:
1258
1259};
1260
1261
1262
1263
1264
1265template <typename DT>
1266inline
1267std::ostream & operator<<(std::ostream & ostr, const Data<DT> & d){
1268 ostr << d.data << ", ODIM:\t "; // .getGeometry()
1269 ostr << d.odim; // << '\n';
1270 //ostr << d.data.properties << '\n';
1271 if (d.hasQuality()){
1272 //ostr << " (has quality field)";
1273 ostr << "+q(" << d.getQuality() << ')';
1274 /*
1275 const PlainData<T,D,M> & q = d.getQuality();
1276 ostr << '\t' << q.data.getGeometry() << '\t';
1277 ostr << q.odim << '\n';
1278 ostr << '\t' << q.data.properties << '\n';
1279 */
1280 }
1281 ostr << '\n';
1282 return ostr;
1283}
1284
1285
1287
1292template <typename DT>
1293class DataSet : public DataGroup<Data<DT>,ODIMPathElem::DATA>, public QualityDataSupport<DT> { // typename T::data_t
1294public:
1295
1296 typedef Data<DT> data_t;
1297 typedef PlainData<DT> plaindata_t;
1298 typedef typename DataGroup<data_t,ODIMPathElem::DATA>::datagroup_t datagroup_t; // ODIMPathElem::DATA>
1299 typedef typename datagroup_t::map_t map_t;
1300
1301
1302 inline
1304 //DataSet(typename data_t::tree_t & tree, const drain::RegExp & quantityRegExp = drain::RegExp()) :
1305 DataSet(typename data_t::tree_t & tree, const QuantitySelector & slct =QuantitySelector()) :
1306 //datagroup_t(tree, quantityRegExp), QualityDataSupport<DT>(tree)
1308 {
1309 }
1310
1311 DataSet(const DataSet<DT> & ds) : datagroup_t(ds), QualityDataSupport<DT>(ds) {
1312 }
1313
1314 ~DataSet(){
1315
1316 drain::Logger mout(__FILE__, __FUNCTION__);
1317 if (this->empty()){
1318 mout.debug3("no data<n> groups, skipping updateTree3" );
1319 }
1320 else {
1321 if (this->size() > 1){
1322 mout.debug("several Data groups, using the first: " , this->begin()->first);
1323 }
1324 const typename DT::odim_t & odim = this->getFirstData().odim;
1325 updateTree3(odim);
1326 }
1327
1328 /*
1329 switch (this->size()) {
1330
1331 case 0:
1332 mout.debug3("no data<n> groups" );
1333 break;
1334 default:
1335 mout.info("several Data groups, using: " , this->begin()->first );
1336 // no break;
1337 case 1:
1338 mout.debug2("updating from 1st data: " , this->begin()->first );
1339
1340
1341 const typename DT::odim_t & odim = this->getFirstData().odim;
1342
1343 // DEBUGGING 2024
1344 // for (const auto & entry: this->baseODIM){
1345 // if (odim[entry.first] == entry.second){
1346 // mout.reject("BaseODIM differs: ", entry.first, ": ", entry.second, " vs ", odim[entry.first]);
1347 // }
1348 // }
1349
1350 // updateTree3(this->getFirstData().odim);
1351 // mout.attention("start updateTree3");
1352 updateTree3(odim);
1353 // mout.attention("end updateTree3");
1354 }
1355 */
1356
1357 }
1358
1359
1360 plaindata_t & getQualityData2(const std::string & quantity = "QIND", const std::string & dataQuantity = ""){ // , bool tmp = false
1361 if (dataQuantity.empty())
1362 return this->getQualityData(quantity);
1363 else {
1364 return this->getData(dataQuantity).getQualityData(quantity);
1365 }
1366 }
1367
1368
1369 const plaindata_t & getQualityData2(const std::string & quantity = "QIND", const std::string & dataQuantity = "") const { // , bool tmp = false
1370 if (dataQuantity.empty())
1371 return this->getQualityData(quantity);
1372 else {
1373 return this->getData(dataQuantity).getQualityData(quantity);
1374 }
1375 }
1376
1377
1378 inline
1379 void updateTree3(const typename DT::odim_t & odim){ //
1380 ODIM::updateH5AttributeGroups<ODIMPathElem::DATASET>(odim, this->tree);
1381 DataTools::updateInternalAttributes(this->tree); // TEST2019/09 // images, including DataSet.data, TODO: skip children
1382 //DataTools::updateInternalAttributes(this->tree, drain::FlexVariableMap()); // TEST2019/09 // images, including DataSet.data, TODO: skip children
1383 }
1384
1385 // TODO: consider this to destructor!
1386 inline
1387 void updateTree3(const typename DT::odim_t & odim) const { //
1388 std::cout << "updateTree3 const \n";
1389 //ODIM::updateH5AttributeGroups<ODIMPathElem::DATASET>(odim, tree);
1390 }
1391
1392
1393
1394protected:
1395
1396
1397
1399
1415};
1416
1418
1421template <typename DT>
1422std::ostream & operator<<(std::ostream & ostr, const DataSet<DT> & d){
1423 typedef DataSet<DT> dataset_t;
1424 ostr << "dataSet ";
1425 char separator = 0;
1427 for (typename dataset_t::const_iterator it = d.begin(); it != d.end(); ++it){
1428 if (separator)
1429 ostr << separator;
1430 else {
1431 separator = ',';
1432 g.setGeometry(it->second.data.getGeometry());
1433 }
1434 ostr << it->first << '[' << drain::Type::getTypeChar(it->second.data.getType()) << ']';
1435 if (it->second.hasQuality())
1436 ostr << "+Q(" << it->second.getQuality() << ')';
1437 }
1438 ostr << " ("<< g << ")";
1439 if (d.hasQuality())
1440 ostr << " +quality(" << d.getQuality() << ')';
1441 /*
1442 ostr << d.data << ", ODIM:\t ";
1443 ostr << d.odim << '\n';
1444 ostr << "props: " << d.data.properties << '\n';
1445 */
1446 return ostr;
1447}
1448
1449
1452// Becoming DEPRECATED
1453//template <typename DT>
1454//class DataSetMap : public std::map<double, DataSet<DT> > {
1455//};
1456
1457// TIMESTAMPED (what::date + what::time data) or path?
1458template <typename DT>
1459class DataSetMap : public std::map<std::string, DataSet<DT> > {
1460};
1461
1462
1463
1464template <typename DT>
1465class DataSetList : public std::list<DataSet<DT> > {
1466};
1467
1468
1469
1470
1471} // rack::
1472
1473namespace drain {
1474
1475template <class T, typename TI, typename D>
1476struct TypeName<rack::DataType<T,TI,D> > {
1477
1478 static const std::string & str(){
1479 static std::string name = drain::StringBuilder<>("DataType<", drain::TypeName<T>::str(), ',', drain::TypeName<TI>::str(), ',', drain::TypeName<D>::str(), ">");
1480 return name;
1481 }
1482
1483};
1484
1485}
1486
1487
1488#endif /* DATA_H_ */
1489
Definition CastableIterator.h:57
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
Logger & error(const TT &... args)
Echoes.
Definition Log.h:426
Definition StringBuilder.h:58
General-purpose key matcher: tests string equality, or regExp, if defined as such.
Definition StringMatcher.h:54
Utilities related to std::type_info.
Definition Type.h:48
Linear scaling and physical range for image intensities.
Definition ValueScaling.h:63
drain::Range< double > physRange
Minimum and maximum physical value of the imaged quantity (not limited to corresponding to minCodeVal...
Definition ValueScaling.h:73
double inv(double y) const
Inverse scaling: given physically meaningful value y, returns the corresponding code value.
Definition ValueScaling.h:301
A map of Variables.
Definition VariableMap.h:61
Definition Geometry.h:143
const iterator & begin()
Returns iterator pointing to the first image element.
Definition ImageFrame.h:118
void setPhysicalRange(const Range< double > &range, bool rescale=false)
Sets the supported range for physical values and optionally adjusts the scaling for maximal resolutio...
Definition ImageFrame.h:105
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition Image.h:183
virtual void setGeometry(size_t width, size_t height, size_t imageChannels=1, size_t alphaChannels=0)
Resizes the image, keeps the current type.
Definition Image.h:87
A map of "data type" group_t (DATA or QUALITY) where the data can be retrieved using quantity keys (s...
Definition Data.h:653
data_t & create(const std::string &quantity)
Creates (or overrides) data array for quantity and scales it.
Definition Data.h:823
static DT::tree_t & init(typename DT::tree_t &t, datagroup_t &dst, const QuantitySelector &slct=QuantitySelector())
Given a dataset h5 subtree, like tree["dataset3"], collects all (or desired) quantities to a data obj...
Definition Data.h:944
DataGroup(typename DT::tree_t &tree, const QuantitySelector &slct=QuantitySelector())
Given a dataset subtree, like tree["dataset3"], constructs a data map of desired quantities.
Definition Data.h:684
Definition Data.h:1465
Definition Data.h:1459
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition Data.h:1293
DataSet(typename data_t::tree_t &tree, const QuantitySelector &slct=QuantitySelector())
Given a dataset subtree, like tree["dataset3"], constructs a data map of desired quantities.
Definition Data.h:1305
static void updateInternalAttributes(Hi5Tree &src)
Copies values of what , where and how attributes to internal attributes down to data[n] groups.
Definition DataTools.cpp:293
Data structure consisting of plain data and an optional quality data.
Definition Data.h:1224
Structure for data storage type, scaling and marker codes. Does not contain quantity.
Definition EncodingODIM.h:70
std::string type
This is non-standard (not in ODIM), but a practical means of handling storage type of datasets.
Definition EncodingODIM.h:157
DOC: Add class description.
Definition ODIMPath.h:82
const std::string & getKey() const
Debugging/logging. Returns standard name. Does not check if type is OTHER.
Definition ODIMPath.h:366
static const group_t WHAT
Metadata group /what , at any depth.
Definition ODIMPath.h:127
static const group_t ARRAY
Data group "data", at deepest level, like /dataset4/data2/quality1/data.
Definition ODIMPath.h:112
static bool getNextChild(const Hi5Tree &tree, ODIMPathElem &child)
Derive a child with index one greater than the largest index encountered.
Definition ODIMPathTools.cpp:106
Essential class for storing radar data.
Definition Data.h:311
void setEncoding(const T &type, const std::string &values="")
Saves type and sets the type of the actual data array as well.
Definition Data.h:371
PlainData(const PlainData< DT2 > &d)
Copy constructor, also for referencing non-const as const.
Definition Data.h:348
void setGeometry(const odim_t &odim)
Copy dimensions of data array and resolution (rscale or xscale,yscale)
Definition Data.h:441
void initializeBest(const EncodingODIM &encoding, const T &...args)
Set encoding and other properties.
Definition Data.h:514
void setGeometry(size_t cols, size_t rows)
Sets dimensions of data array and metadata.
Definition Data.h:424
void copyGeometry(const PlainData< DT2 > &srcData)
Copy dimensions of data array and resolution (rscale or xscale,yscale)
Definition Data.h:454
void copyEncoding(const EncodingODIM &odim)
Adjust data array and ODIM metadata to given encoding. Recommended form.
Definition Data.h:384
void initializeBest(const std::string &type, const T &...args)
Set storage type and other properties.
Definition Data.h:498
void initializeBest(const drain::image::AreaGeometry &geometry, const T &...args)
Set width and height of the data array, and set other properties.
Definition Data.h:506
void createSimpleQualityData(PlainData< DT > &qualityData, double dataQuality=1.0, double undetectQuality=0.5, double nodataQuality=0.0) const
For this data, creates an on-off quality data.
Definition Data.h:544
void initializeBest(const std::type_info &type, const T &...args)
Set storage type and other properties.
Definition Data.h:490
void createSimpleQualityData(drain::image::Image &qualityImage, double dataQuality=1.0, double undetectQuality=0.5, double nodataQuality=0.0) const
For this data, creates an on-off quality data.
Definition Data.h:569
void updateTree2()
TODO: consider this to destructor.
Definition Data.h:554
void initializeBest()
Terminal step in initialisation: set actual data storage type and resize.
Definition Data.h:482
void copyEncoding(const PlainData< DT2 > &srcData)
Adjust data array and ODIM metadata to given encoding. Recommended form.
Definition Data.h:403
void setGeometry(const drain::image::AreaGeometry &geometry)
Sets dimensions of data array and metadata.
Definition Data.h:431
PlainData(typename DT::tree_t &tree, const std::string &quantity)
Constructor referring to HDF5 structure.
Definition Data.h:329
void initialize(const T &type, size_t cols, size_t rows)
Calls setEncoding() and setGeometry().
Definition Data.h:467
Base class providing quality support for Dataand DataSet
Definition Data.h:1112
const plaindata_t & getQualityData(const std::string &quantity="QIND") const
Finds associated quality data - maybe empty and unscaled.
Definition Data.h:1137
plaindata_t & getQualityData(const std::string &quantity="QIND")
Finds associated quality data - maybe empty and unscaled.
Definition Data.h:1162
Experimental structure, designed only for accessing root level metadata.
Definition Data.h:261
Base class for all kinds of radar data.
Definition Data.h:155
tree_t & tree
General HDF5 data structure.
Definition Data.h:218
Namespace for images and image processing tools.
Definition AccumulationArray.cpp:45
Definition Data.h:1473
Definition AltitudeOp.cpp:42
SrcType< PolarODIM const > PolarSrc
Read-only data in polar coordinates.
Definition Data.h:125
DstType< VerticalProfileODIM > VprDst
Writable data in vertical coordinates, with profile metadata.
Definition Data.h:143
SrcType< CartesianODIM const > CartesianSrc
Read-only data in Cartesian coordinates.
Definition Data.h:128
std::ostream & operator<<(std::ostream &ostr, const PlainData< DT > &d)
Definition Data.h:631
DstType< PolarODIM > PolarDst
Writable data in polar coordinates.
Definition Data.h:134
SrcType< ODIM const > BasicSrc
Read-only data (supports top-level ODIM properties only)
Definition Data.h:122
DstType< CartesianODIM > CartesianDst
Writable data in Cartesian coordinates.
Definition Data.h:137
DstType< RhiODIM > RhiDst
Writable data in vertical coordinates, with (pseudo) RHI metadata.
Definition Data.h:140
Default implementation.
Definition TypeName.h:54
static const std::string & str()
Default implementation: name returned by std::type_info::name()
Definition TypeName.h:68
Container that couples together a tree structure and a data array (drain::image::Image),...
Definition Data.h:83
Writable data type.
Definition Data.h:117
Read-only data type.
Definition Data.h:107