40 #include <drain/RegExp.h>
42 #include <drain/util/ReferenceMap.h>
43 #include <drain/util/StringMatcherList.h>
47 #include "PolarODIM.h"
48 #include "CartesianODIM.h"
49 #include "VerticalODIM.h"
50 #include "DataSelector.h"
51 #include "DataTools.h"
87 template <
typename T,
typename TI,
typename D>
90 typedef TI tree_iter_t;
111 template <
typename M = PolarODIM const>
112 struct SrcType :
public DataType<Hi5Tree const, Hi5Tree::const_iterator, Image const> {
121 template <
typename M = PolarODIM>
159 template <
typename DT>
163 typedef DT datatype_t;
164 typedef typename DT::tree_t tree_t;
165 typedef typename DT::tree_iter_t tree_iter_t;
169 return getAttr<ODIMPathElem::WHAT>();
174 return getAttr<ODIMPathElem::WHAT>();
179 return getAttr<ODIMPathElem::WHERE>();
184 return getAttr<ODIMPathElem::WHERE>();
190 return getAttr<ODIMPathElem::HOW>();
195 return getAttr<ODIMPathElem::HOW>();
200 void setExcluded(
bool exclude =
true){
201 this->tree.data.exclude = exclude;
206 bool isExcluded()
const {
207 return this->tree.data.exclude;
213 const tree_t & getTree()
const {
return this->tree; };
217 tree_t & getTree(){
return this->tree; } ;
243 template <ODIMPathElem::group_t G>
245 return this->tree[ODIMPathElem(G)].data.attributes;
248 template <ODIMPathElem::group_t G>
250 return this->tree[ODIMPathElem(G)].data.attributes;
265 template <
typename DT>
272 this->odim.copyFrom(tree.data.image);
279 mout.experimental<LOG_DEBUG>(
"invoking ODIM::updateH5AttributeGroups<ODIMPathElem::ROOT>()");
280 mout.experimental<LOG_DEBUG-1>(
"root odim: ", this->odim);
282 ODIM::updateH5AttributeGroups<ODIMPathElem::ROOT>(this->odim, this->tree);
283 DataTools::updateInternalAttributes(this->tree);
287 typename DT::odim_t odim;
301 template <
typename DT>
305 typedef typename DT::tree_t tree_t;
306 typedef typename DT::image_t image_t;
307 typedef typename DT::odim_t odim_t;
313 data(tree[ODIMPathElem::ARRAY].data.image),
314 odim(data, data.properties.get(
"what:quantity",
""))
320 PlainData(
typename DT::tree_t & tree,
const std::string & quantity) :
338 template <
typename DT2>
359 void setEncoding(
const T & type,
const std::string & values =
""){
361 this->odim.type = drain::Type::getTypeChar(
drain::Type(type));
362 this->odim.setTypeDefaults(type, values);
371 data.setType(this->odim.
type);
372 data.setScaling(this->odim.scaling);
379 this->odim.importMap(srcData.odim);
380 data.setType(this->odim.type);
381 data.setScaling(this->odim.scaling);
385 void setPhysicalRange(
double min,
double max){
387 data.setPhysicalRange(min, max,
true);
389 this->odim.scaling.assignSequence(data.getScaling());
399 this->odim.setGeometry(cols, rows);
400 data.setGeometry(cols, rows);
406 this->odim.setGeometry(geometry.getWidth(), geometry.getHeight());
407 data.setGeometry(geometry);
416 this->odim.setGeometry(odim.area);
417 data.setGeometry(odim.area);
419 this->odim.resolution = odim.resolution;
429 setGeometry(srcData.odim);
443 setGeometry(cols, rows);
450 setGeometry(geometry);
464 void createSimpleQualityData(
drain::image::Image & qualityImage,
double dataQuality=1.0,
double undetectQuality=0.5,
double nodataQuality=0.0)
const;
471 createSimpleQualityData(qualityData.data, dataQuality, undetectQuality, nodataQuality);
472 qualityData.odim.scaling.set(qualityData.data.getScaling());
480 ODIM::updateH5AttributeGroups<ODIMPathElem::DATA>(this->odim, this->tree);
481 DataTools::updateInternalAttributes(this->tree);
493 template <
typename DT>
500 const bool DATA = !std::isnan(dataQuality);
501 const bool UNDETECT = !std::isnan(undetectQuality);
502 const bool NODATA = !std::isnan(nodataQuality);
505 const double dataCode = DATA ? scaling.
inv(dataQuality) : 0.0;
506 const double undetectCode = UNDETECT ? scaling.
inv(undetectQuality) : 0.0;
507 const double nodataCode = NODATA ? scaling.
inv(nodataQuality) : 0.0;
509 quality.
setGeometry(data.getWidth(), data.getHeight());
511 Image::iterator it = data.begin();
512 Image::iterator wit = quality.
begin();
513 while (it != data.end()){
515 if (UNDETECT && (*it == this->odim.undetect))
517 else if (NODATA && (*it == this->odim.nodata))
554 template <
typename DT>
557 ostr << d.data <<
", ODIM:\t ";
558 ostr << d.odim <<
'\n';
559 ostr <<
"props: " << d.data.properties <<
'\n';
577 template <
class DT, ODIMPathElem::group_t G>
583 typedef typename DT::datatype_t datatype_t;
584 typedef std::map<std::string, DT > map_t;
611 init(tree, *
this, slct);
649 bool has(
const std::string & quantity)
const {
650 return (this->find(quantity) != this->end());
653 const data_t & getData(
const std::string & quantity)
const {
654 return getData(quantity.c_str());
658 const data_t & getData(
const char *quantity)
const {
661 drain::Logger mout(__FUNCTION__,
"DataGroup{" + ODIMPathElem::getKey(G) +
"}");
663 typename datagroup_t::const_iterator it = this->find(quantity);
665 if (it != this->end()){
666 mout.debug3(
'[' , quantity ,
"]\t = " , it->first );
670 mout.debug(
'[' , quantity ,
"] not found, returning empty" );
675 data_t & getData(
const std::string & quantity) {
676 return getData(quantity.c_str());
680 data_t & getData(
const char *quantity) {
683 drain::Logger mout(__FUNCTION__,
"DataGroup{" + ODIMPathElem::getKey(G) +
"}");
686 typename datagroup_t::iterator it;
689 it = this->find(quantity);
690 if (it != this->end()){
691 mout.debug3(
"found " , it->first );
695 ODIMPathElem child(G);
696 ODIMPathTools::getNextChild(this->tree, child);
697 mout.debug3(
"add: " , child ,
" [" , quantity ,
']' );
698 it = this->insert(this->begin(),
typename map_t::value_type(quantity, DT(this->getTree()[child], quantity)));
710 drain::Logger mout(__FUNCTION__,
"(KeySelector): ",
"DataGroup{" + ODIMPathElem::getKey(G)+
"}");
714 for (
const auto & entry: *
this){
715 if (m.test(entry.first)){
716 mout.debug(
"quantity " , entry.first ,
" matches " , slct);
731 mout.note(
"no quantity matched with " , slct);
743 data_t &
create(
const std::string & quantity) {
744 data_t & d = getData(quantity);
751 data_t & getFirstData() {
753 for (
auto & entry: *
this){
754 if (!entry.second.isExcluded()){
759 drain::Logger(__FILE__, __LINE__,
"DataGroup{" + ODIMPathElem::getKey(G)+
"}:", __FUNCTION__).
error(
"no data");
761 return this->getData(
"");
778 const data_t & getFirstData()
const {
780 for (
const auto & entry: *
this){
781 if (!entry.second.isExcluded()){
786 drain::Logger(__FILE__, __LINE__,
"DataGroup{" + ODIMPathElem::getKey(G)+
"}:", __FUNCTION__).
error(
"no data");
787 return this->getData(
"");
812 data_t & getLastData() {
814 const typename datagroup_t::reverse_iterator it = this->rend();
816 if (it == this->rbegin()){
817 drain::Logger mout(__FUNCTION__,
"DataGroup{" + ODIMPathElem::getKey(G)+
"}");
818 mout.error(
"no data" );
819 return this->getData(
"");
827 const data_t & getLastData()
const {
829 drain::Logger mout(__FUNCTION__,
"DataGroup{" + ODIMPathElem::getKey(G) +
"}-const");
833 typename datagroup_t::const_reverse_iterator it = this->rend();
835 if (it != this->rbegin()){
836 mout.debug2(
"found: " , it->first );
840 mout.note(
"not found, returning empty" );
851 const data_t & getEmpty() {
852 static typename DT::tree_t t;
853 static data_t empty(t);
868 drain::Logger mout(__FUNCTION__,
"DataGroup{" + ODIMPathElem::getKey(G)+
"}");
871 const bool USE_SELECTOR = slct.isSet();
874 unsigned short counter = 0;
876 mout.debug3(
"collecting data items, selector='", slct,
"'");
885 const std::string datasetQuantity = t[ODIMPathElem::WHAT].data.attributes.get(
"quantity",
"");
888 for (
auto & entry: t){
891 if (! (entry.first.is(G))){
898 const std::string dataQuantity = entry.second[ODIMPathElem::WHAT].data.attributes.get(
"quantity",
"");
900 const std::string & quantity = !dataQuantity.empty() ? dataQuantity : datasetQuantity;
904 if (!slct.
test(quantity)){
908 mout.debug3(
"rejected '" , entry.first ,
"' [" , quantity ,
"] !~" , slct );
925 mout.
accept<LOG_DEBUG+2>(
"accept '", entry.first,
"' [", quantity,
']' );
934 if (quantity.empty()){
936 mout.info(
"quantities dataset:'", datasetQuantity,
"', data:'", dataQuantity,
"'");
937 mout.
warn(
"undefined quantity in ", entry.first,
", using key=", entry.first );
939 dst.insert(
typename map_t::value_type(entry.first, DT(entry.second, entry.first)));
943 if (dst.find(quantity) != dst.end()){
945 mout.
warn(
"quantity '" , quantity ,
"' replaced same quantity at " , entry.first );
947 dst.insert(
typename map_t::value_type(quantity, DT(entry.second, quantity)));
957 mout.debug3(
"matched " , dst.size() ,
"(out of " , counter ,
") data items with selector: " , slct ,
'/' );
960 mout.debug3(
"collected " , dst.size() ,
" data items" );
968 typename DT::tree_t & adapt(
const datagroup_t & src, datagroup_t & dst){
970 drain::Logger mout(__FUNCTION__,
"DataGroup{" + ODIMPathElem::getKey(G)+
"}");
976 mout.debug3(
"src empty" );
980 for (
const auto & entry: src){
992 mout.debug3(
"adapted ", dst.size(),
" data items; ", src.begin()->first,
"...");
1001 template <
class DT, ODIMPathElem::group_t G>
1002 std::ostream & operator<<(std::ostream & ostr,
const DataGroup<DT,G> & d){
1006 for (
typename DataGroup<DT,G>::const_iterator it = d.begin(); it != d.end(); ++it){
1011 g.setGeometry(it->second.data.getGeometry());
1013 ostr << it->first <<
'[' << drain::Type::getTypeChar(it->second.data.getType()) <<
']';
1015 ostr <<
" ("<< g <<
")";
1031 template <
typename DT>
1058 return this->quality.getData(quantity);
1083 return this->quality.getData(quantity);
1088 bool hasQuality()
const {
1089 return !this->quality.empty();
1093 bool hasQuality(
const std::string & quantity)
const {
1094 return this->quality.find(quantity) != this->quality.end();
1098 const qualitygroup_t & getQuality()
const {
1099 return this->quality;
1103 qualitygroup_t & getQuality(){
1104 return this->quality;
1122 qualitygroup_t quality;
1143 template <
typename DT>
1165 mout.experimental(
"Swapping...");
1166 this->tree.swap(d.
tree);
1168 typename DT::odim_t odim;
1169 odim.updateFromMap(this->odim);
1170 this->odim.updateFromMap(d.odim);
1171 d.odim.updateFromMap(odim);
1173 this->updateTree2();
1185 template <
typename DT>
1187 std::ostream & operator<<(std::ostream & ostr,
const Data<DT> & d){
1188 ostr << d.data <<
", ODIM:\t ";
1191 if (d.hasQuality()){
1193 ostr <<
"+q(" << d.getQuality() <<
')';
1212 template <
typename DT>
1219 typedef typename datagroup_t::map_t map_t;
1238 switch (this->size()) {
1240 mout.debug3(
"no data<n> groups" );
1243 mout.info(
"several Data groups, using: " , this->begin()->first );
1246 mout.debug(
"updating from 1st data: " , this->begin()->first );
1249 const typename DT::odim_t & odim = this->getFirstData().odim;
1269 plaindata_t & getQualityData2(
const std::string & quantity =
"QIND",
const std::string & dataQuantity =
""){
1270 if (dataQuantity.empty())
1271 return this->getQualityData(quantity);
1273 return this->getData(dataQuantity).getQualityData(quantity);
1278 const plaindata_t & getQualityData2(
const std::string & quantity =
"QIND",
const std::string & dataQuantity =
"")
const {
1279 if (dataQuantity.empty())
1280 return this->getQualityData(quantity);
1282 return this->getData(dataQuantity).getQualityData(quantity);
1288 void updateTree3(
const typename DT::odim_t & odim){
1289 ODIM::updateH5AttributeGroups<ODIMPathElem::DATASET>(odim, this->tree);
1290 DataTools::updateInternalAttributes(this->tree);
1296 void updateTree3(
const typename DT::odim_t & odim)
const {
1297 std::cout <<
"updateTree3 const \n";
1330 template <
typename DT>
1331 std::ostream & operator<<(std::ostream & ostr,
const DataSet<DT> & d){
1336 for (
typename dataset_t::const_iterator it = d.begin(); it != d.end(); ++it){
1341 g.setGeometry(it->second.data.getGeometry());
1343 ostr << it->first <<
'[' << drain::Type::getTypeChar(it->second.data.getType()) <<
']';
1344 if (it->second.hasQuality())
1345 ostr <<
"+Q(" << it->second.getQuality() <<
')';
1347 ostr <<
" ("<< g <<
")";
1349 ostr <<
" +quality(" << d.getQuality() <<
')';
1367 template <
typename DT>
1373 template <
typename DT>
1384 template <
class T,
typename TI,
typename D>
1387 static const std::string & str(){
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:412
Logger & accept(const TT &... args)
Some input has been accepted, for example by a syntax.
Definition: Log.h:578
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
void importMap(const std::map< std::string, S > &m)
Assign values from a map, overriding existing entries.
Definition: SmartMap.h:252
Definition: StringBuilder.h:58
bool test(const std::string &key, bool defaultResult=true) const
Check if key is accepted.
Definition: StringMatcherList.h:204
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:51
Linear scaling and physical range for image intensities.
Definition: ValueScaling.h:64
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:119
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:106
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition: Image.h:184
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:95
A map of "data type" group_t (DATA or QUALITY) where the data can be retrieved using quantity keys (s...
Definition: Data.h:578
DataGroup(typename DT::tree_t &tree, const drain::KeySelector &slct=drain::KeySelector())
Given a dataset subtree, like tree["dataset3"], constructs a data map of desired quantities.
Definition: Data.h:609
data_t & create(const std::string &quantity)
Creates (or overrides) data array for quantity and scales it.
Definition: Data.h:743
static DT::tree_t & init(typename DT::tree_t &t, datagroup_t &dst, const drain::KeySelector &slct=drain::KeySelector())
Given a dataset h5 subtree, like tree["dataset3"], collects all (or desired) quantities to a data obj...
Definition: Data.h:864
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition: Data.h:1213
DataSet(typename data_t::tree_t &tree, const drain::KeySelector &slct=drain::KeySelector())
Given a dataset subtree, like tree["dataset3"], constructs a data map of desired quantities.
Definition: Data.h:1225
Data structure consisting of plain data and an optional quality data.
Definition: Data.h:1144
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:146
Definition: ODIMPath.h:82
Essential class for storing radar data.
Definition: Data.h:302
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:359
PlainData(const PlainData< DT2 > &d)
Copy constructor, also for referencing non-const as const.
Definition: Data.h:339
void setGeometry(const odim_t &odim)
Copy dimensions of data array and resolution (rscale or xscale,yscale)
Definition: Data.h:415
void setGeometry(size_t cols, size_t rows)
Sets dimensions of data array and metadata.
Definition: Data.h:398
void copyGeometry(const PlainData< DT2 > &srcData)
Copy dimensions of data array and resolution (rscale or xscale,yscale)
Definition: Data.h:428
void copyEncoding(const EncodingODIM &odim)
New, experimental.
Definition: Data.h:369
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:469
void updateTree2()
TODO: consider this to destructor.
Definition: Data.h:479
void setGeometry(const drain::image::AreaGeometry &geometry)
Sets dimensions of data array and metadata.
Definition: Data.h:405
PlainData(typename DT::tree_t &tree, const std::string &quantity)
Constructor referring to HDF5 structure.
Definition: Data.h:320
void initialize(const T &type, size_t cols, size_t rows)
Calls setEncoding() and setGeometry().
Definition: Data.h:441
Base class providing quality support for Dataand DataSet
Definition: Data.h:1032
plaindata_t & getQualityData(const std::string &quantity="QIND")
Finds associated quality data - maybe empty and unscaled.
Definition: Data.h:1082
const plaindata_t & getQualityData(const std::string &quantity="QIND") const
Finds associated quality data - maybe empty and unscaled.
Definition: Data.h:1057
Experimental structure, designed only for accessing root level metadata.
Definition: Data.h:266
Base class for all kinds of radar data.
Definition: Data.h:160
tree_t & tree
General HDF5 data structure.
Definition: Data.h:217
Namespace for images and image processing tools.
Definition: AccumulationArray.cpp:45
Definition: DataSelector.cpp:1277
Definition: DataSelector.cpp:44
Container that couples together a tree structure and a data array (drain::image::Image),...
Definition: Data.h:88
Writable data type.
Definition: Data.h:122
Read-only data type.
Definition: Data.h:112