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