ProductOp.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 /*
32  * ProductOp.h
33  *
34  * Created on: Mar 7, 2011
35  * Author: mpeura
36  */
37 
38 #ifndef RACK_PRODUCT_OP
39 #define RACK_PRODUCT_OP "ProductOP"
40 
41 //#include <exception>
42 #include <drain/Log.h>
43 #include <iostream>
44 #include <list>
45 #include <map>
46 #include <set>
47 #include <string>
48 
49 #include <drain/RegExp.h>
50 #include <drain/util/SmartMap.h>
51 #include <drain/util/TreeOrdered.h>
52 
53 #include "data/Data.h"
54 #include "data/DataSelector.h"
55 #include "data/ODIM.h"
56 #include "data/ODIMPath.h"
57 #include "data/ODIMPathTools.h"
58 #include "data/QuantityMap.h"
59 
60 #include "hi5/Hi5.h"
61 //#include "main/rack.h"
62 
63 
64 
65 #include "ProductBase.h"
66 
67 namespace rack {
68 
69 using namespace drain::image;
70 
71 
73 
77 template <class MS, class MD>
78 class ProductOp : public ProductBase {
79 
80 public:
81 
84 
86  typedef DstType<MD> dst_t;
87 
88 
90  inline
91  ProductOp(const std::string &name, const std::string & description) : ProductBase(name, description) {
92  // dataSelector.path = "^.* / da ta[0-9]+/?$"; /// Contract: in Op's, path filters should be copy to group level.
93  }
94 
95  inline
96  ProductOp(const ProductOp & product) : ProductBase(product){
97  std::cerr << '#' << __FUNCTION__ << " copy ct " << product.getName() << this->dataSelector << '\n';
98  };
99 
101  MD odim;
102 
104  /*
105  virtual inline
106  const std::string & getOutputQuantity() const {
107  return odim.quantity; //outputQuantity;
108  }
109  */
110 
112 
115  virtual inline
116  const std::string & getOutputQuantity(const std::string & inputQuantity = "") const {
117  if (!odim.quantity.empty())
118  return odim.quantity; //outputQuantity;
119  else
120  return inputQuantity;
121  }
122 
123 
124  //void processH5() // see MotionFill
125  virtual // HistogramOp
126  void processH5(const Hi5Tree &src, Hi5Tree &dst) const;
127 
128 
130 
134  virtual
135  void computeSingleProduct(const DataSetMap<src_t> & srcSweeps, DataSet<dst_t> & dstProduct) const;
136 
138 
145  virtual
146  void processDataSet(const DataSet<src_t > & srcSweep, DataSet<DstType<MD> > & dstProduct) const;
147 
148  virtual
149  void processData(const Data<src_t > & srcData, Data<dst_t > & dstData) const {
150  drain::Logger mout(__FILE__, __FUNCTION__);
151  mout.unimplemented(__FUNCTION__);
152  };
153 
154 
155 protected:
156 
157 
159 
167  virtual
168  void setGeometry(const MS & srcODIM, PlainData<dst_t > & dstData) const = 0; // {};
169 
170 
172 
175  virtual inline
176  void initDst(const MS & srcODIM, PlainData<dst_t > & dstData) const {
177 
178  drain::Logger mout(__FILE__, __FUNCTION__); //REPL this->name+"(VolumeOp<M>)", __FUNCTION__);
179 
180  setEncoding(srcODIM, dstData);
181  setGeometry(srcODIM, dstData);
182 
183  mout.debug("final dstData: " , dstData );
184  }
185 
186 
188 
196  //virtual
197  //void setEncodingNEW(PlainData<dst_t > & dstData) const;
198 
200 
209  virtual
210  void setEncoding(const ODIM & srcODIM, PlainData<dst_t > & dstData) const;
211 
213 
224  // void ProductOp<MS,MD>::setEncodingNEW
225  void setEncodingNEW(PlainData<dst_t> & dstData, const std::string quantity = "", const std::string type = "") const;
226 
227  /*
228  static
229  void handleEncodingRequest(const std::string & encoding, PlainData<dst_t> & dst){
230 
231  drain::Logger mout(__FILE__, __FUNCTION__);
232 
233  ProductBase::completeEncoding(dst.odim, encoding);
234 
235  if (!dst.odim.type.empty())
236  dst.data.setType(dst.odim.type);
237  else
238  dst.odim.type = (const char)dst.data.getType2();
239 
240  }
241  */
242 };
243 
250 template <class MS, class MD>
252  const std::string quantity, const std::string type) const {
253 
254  drain::Logger mout(__FILE__, __FUNCTION__);
255 
256  if (dstData.odim.quantity.empty())
257  dstData.odim.quantity = quantity;
258 
259  if (!type.empty())
260  dstData.odim.type = type;
261 
262  const std::string & qty = quantity.empty() ? dstData.odim.quantity : quantity;
263 
264  if (qty.empty()){
265  mout.warn("No quantity in metadata or as argument" );
266  }
267 
268  const QuantityMap & qmap = getQuantityMap();
269  qmap.setQuantityDefaults(dstData, qty, dstData.odim.type);
270  dstData.odim.updateValues(targetEncoding);
271  qmap.setQuantityDefaults(dstData, qty, dstData.odim.type); // type also?
272  dstData.odim.updateValues(targetEncoding);
273  // update
274  dstData.data.setScaling(odim.scaling);
275 
277  // dstData.odim.product = odim.product; ?
278 }
279 
280 /*
281 template <class MS, class MD>
282 void ProductOp<MS,MD>::setEncodingNEW(PlainData<dst_t> & dst, const std::string quantity = "", const std::string type = "") const {
283 
284  drain::Logger mout(__FILE__, __FUNCTION__);
285 
286  if (odim.quantity.empty())
287  odim.quantity = quantity;
288 
289  if (!type.empty())
290  odim.type = type;
291 
292  const std::string & qty = quantity.empty() ? odim.quantity : quantity;
293 
294  const QuantityMap & qmap = getQuantityMap();
295  qmap.setQuantityDefaults(dst, qty, odim.type);
296  dst.odim.updateValues(targetEncoding);
297  qmap.setQuantityDefaults(dst, qty, dst.odim.type); // type also?
298  dst.odim.updateValues(targetEncoding);
299  // update
300  dst.data.setScaling(dst.odim.scaling);
301 
303  // dst.odim.product = odim.product; ?
304 }
305 */
306 
307 template <class MS, class MD>
308 void ProductOp<MS,MD>::setEncoding(const ODIM & inputODIM, PlainData<dst_t> & dst) const {
309 
310  ProductBase::applyODIM(dst.odim, this->odim);
311  ProductBase::applyODIM(dst.odim, inputODIM, true); // New. Use defaults if still unset
312  ProductBase::completeEncoding(dst.odim, this->targetEncoding);
313 
314  // Set actual scaling up to date with metadata)
315  dst.data.setScaling(dst.odim.scaling);
317  // dst.odim.product = odim.product;
318 }
319 
320 
321 template <class MS, class MD> // copied from VolumeOp::processVolume
322 void ProductOp<MS,MD>::processH5(const Hi5Tree &src, Hi5Tree &dst) const {
323 
324  //drain::Logger mout(__FILE__, __FUNCTION__); //REPL this->name+"(VolumeOp<M>)", __FUNCTION__);
325  drain::Logger mout(__FILE__, __FUNCTION__);
326 
327  mout.debug("start");
328  mout.warn(*this);
329  mout.debug2("DataSelector: ", this->dataSelector);
330 
331  // Step 1: collect sweeps (/datasetN/)
332  //DataSetMap<src_t> sweeps;
333  DataSetMap<src_t> sweeps;
334 
336  mout.debug3("collect the applicable paths");
337  ODIMPathList dataPaths; // Down to ../dataN/ level, eg. /dataset5/data4
338  int index = 0;
339 
340 
341  mout.unimplemented("No index generator defined!");
342  // NEW
343  this->dataSelector.getPaths(src, dataPaths); //, ODIMPathElem::DATASET);
344  mout.debug3("populate the dataset map, paths=" , dataPaths.size() );
345  //for (ODIMPathList::const_iterator it = dataPaths.begin(); it != dataPaths.end(); ++it){
346  for (const ODIMPath & path: dataPaths){
347  mout.debug3("add: " , index , '\t' , path );
348  //sweeps.insert(typename DataSetMap<src_t>::value_type("indexxx", DataSet<src_t>(src(path), drain::RegExp(this->dataSelector.getQuantity()) ))); // Something like: sweeps[elangle] = src[parent] .
349  sweeps.insert(typename DataSetMap<src_t>::value_type("indexxx", DataSet<src_t>(src(path), this->dataSelector.getQuantitySelector() ))); // Something like: sweeps[elangle] = src[parent] .
350  }
351 
352 
353  // OLD
354  /*
355  this->dataSelector.getPaths(src, dataPaths, ODIMPathElem::DATA);
356 
357  mout.debug3("populate the dataset map, paths=" , dataPaths.size() );
358  std::set<ODIMPath> parents;
359 
360  for (ODIMPathList::const_iterator it = dataPaths.begin(); it != dataPaths.end(); ++it){
361 
362  ODIMPath parent = *it;
363  parent.pop_back();
364 
365  mout.debug3("check " , *it );
366 
367  if (parents.find(parent) == parents.end()){
368  mout.debug3("add " , parent , "=>" , index );
369  // kludge (index ~ elevation)
370  sweeps.insert(typename DataSetMap<src_t>::value_type(index, DataSet<src_t>(src(parent), drain::RegExp(this->dataSelector.quantity) ))); // Something like: sweeps[elangle] = src[parent] .
371  //elangles << elangle;
372  }
373  }
374  */
375 
376 
377  mout.debug2("DataSets: " , sweeps.size() );
378 
379 
380  // Copy metadata from the input volume (note that dst may have been cleared above)
381  for (const auto key: {ODIMPathElem::WHAT, ODIMPathElem::WHERE, ODIMPathElem::HOW}){
382  // .data.attributes
383  mout.unimplemented("consider and test .data.attributes instead");
384  dst[key] = src[key];
385  }
386  // odim.copyToRoot(dst); NO! Mainly overwrites original data. fgrep 'declare(rootAttribute' odim/*.cpp
387 
388  //ODIMPath dataSetPath;
389  ODIMPathElem parent(ODIMPathElem::DATASET); // /dataset1
390  ODIMPathElem child(ODIMPathElem::DATA); // /dataset1
391 
392  mout.note(DRAIN_LOG_VAR(ProductBase::appendResults));
394  ODIMPathTools::getNextChild(dst, parent);
395  }
396 
397  ODIMPathTools::getNextChild(dst[parent], child);
398 
399  mout.attention("storing product in path: " , parent , '|' , child );
400  Hi5Tree & dstProduct = dst[parent][child]; // (dataSetPath);
401 
403  {
404  DataSet<dst_t> dstProductDataset(dstProduct); // PATH
405  this->computeSingleProduct(sweeps, dstProductDataset);
406  }
407 
408  dst["what"].data.attributes["object"] = this->odim.object;
409  dstProduct["what"].data.attributes["product"] = odim.product;
410  dstProduct["what"].data.attributes["prodpar"] = odim.prodpar;
411 
412  ProductBase::setRackVersion(dstProduct["how"].data.attributes);
413  // how["elangles"] = elangles; // This service could be lower in hierarchy (but for PseudoRHI and pCappi ok here)
414 
415 }
416 
417 
418 //template <class M>
419 template <class MS, class MD>
421 
422  drain::Logger mout(__FILE__, __FUNCTION__); //REPL this->name+"(VolumeOp<M>)", __FUNCTION__);
423  mout.debug3("start" );
424 
425  if (src.size() == 0)
426  mout.warn("no data" );
427 
428  //for (typename DataSetMap<src_t >::const_iterator it = src.begin(); it != src.end(); ++it) {
429  for (const auto & entry: src) {
430  mout.debug3("calling processDataSet for elev=", entry.first, " #datasets=", entry.second.size());
431  processDataSet(entry.second, dstProduct);
432  // TODO: detect first init?
433  // mout.warn("OK" );
434  }
435 
437  // mout.warn("getFirst data" );
438  //@ Data<DstType<MD> > & dstData = dstProduct.getFirstData(); // main data
439  //@ dstProduct.updateTree(dstData.odim);
440  // mout.warn("end" );
441 }
442 
443 
444 //template <class M>
445 template <class MS, class MD>
446 void ProductOp<MS,MD>::processDataSet(const DataSet<src_t > & srcSweep, DataSet<DstType<MD> > & dstProduct) const {
447 
448  //drain::Logger mout(__FILE__, __FUNCTION__); //REPL this->name+"(ProductOp<MS,MD>)", __FUNCTION__);
449  drain::Logger mout(__FILE__, __FUNCTION__);
450 
451  mout.debug("start" );
452 
453  const Data<src_t > & srcData = srcSweep.getFirstData();
454 
455  mout.debug("target quantity: " , odim.quantity );
456 
457  // NEW 2020/06
458  const std::string & quantity = !odim.quantity.empty() ? odim.quantity : srcData.odim.quantity;
459  Data<DstType<MD> > & dstData = dstProduct.getData(quantity);
460  dstData.odim.quantity = quantity;
461 
462  // OLD
463  // Data<DstType<MD> > & dstData = !odim.quantity.empty() ? dstProduct.getData(odim.quantity) : dstProduct.getFirstData();
464  //if (dstData.odim.quantity.empty())
465  // dstData.odim.quantity = odim.quantity;
466 
467  //mout.debug("calling setEncoding" );
468  //setEncoding(srcData.odim, dstData.odim);
469  this->initDst(srcData.odim, dstData);
470 
471  //mout.warn("calling processData" );
472  processData(srcData, dstData);
473  //mout.warn("updateTree" );
474  //@ dstData.updateTree();
475 }
476 
477 
478 
479 
480 
481 } // namespace rack
482 
483 
484 #endif /* RACKOP_H_ */
485 
486 // Rack
487  // REP
488  // REP // REP // REP // REP
virtual const std::string & getName() const
Return the name of an instance.
Definition: BeanLike.h:69
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:310
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition: Log.h:474
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition: Log.h:509
Logger & note(const TT &... args)
For top-level information.
Definition: Log.h:487
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:428
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:678
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:688
Definition: Path.h:112
Computes dot product of intensities of two images.
Definition: PixelVectorOp.h:364
Definition: Data.h:1368
A map of radar data, indexed by quantity code (DBZH, VRAD, etc).
Definition: Data.h:1213
Data structure consisting of plain data and an optional quality data.
Definition: Data.h:1144
Definition: ODIMPath.h:82
static const group_t WHAT
Metadata group /what , at any depth.
Definition: ODIMPath.h:127
static const group_t DATASET
First level group, /dataset + digit .
Definition: ODIMPath.h:106
static const group_t HOW
Metadata group /how , at any depth.
Definition: ODIMPath.h:133
static const group_t DATA
Second level group, /data + digit .
Definition: ODIMPath.h:109
static const group_t WHERE
Metadata group /where , at any depth.
Definition: ODIMPath.h:130
static bool getNextChild(const Hi5Tree &tree, ODIMPathElem &child)
Derive a child with index one greater than the largest index encountered.
Definition: ODIMPathTools.cpp:96
ODIM metadata (quantity, gain, offset, undetect, nodata, date, time)
Definition: ODIM.h:79
Essential class for storing radar data.
Definition: Data.h:302
Base class for radar data processors. Input can be in polar or Cartesian coordinates.
Definition: ProductBase.h:82
static void applyODIM(ODIM &productODIM, const ODIM &srcODIM, bool applyDefaults=false)
Sets target quantity and encoding, if unset. If input odim.
Definition: ProductBase.cpp:117
static void completeEncoding(ODIM &productODIM, const std::string &targetEncoding)
Modifies encoding. If type is changed, resets scaling first.
Definition: ProductBase.cpp:183
ODIMPathElem appendResults
If set, appends outputs in an hdf5 structure instead of overwriting.
Definition: ProductConf.h:93
DstType< MD > dst_t
Type of output, that is, destination.
Definition: ProductOp.h:86
SrcType< MS const > src_t
Type of input, that is, source.
Definition: ProductOp.h:83
MD odim
The default data parameters for encoding output (the product).
Definition: ProductOp.h:98
virtual const std::string & getOutputQuantity(const std::string &inputQuantity="") const
Returns the primary output quantity (ODIM what:quantity , like DBZH)
Definition: ProductOp.h:116
virtual void initDst(const MS &srcODIM, PlainData< dst_t > &dstData) const
initialises dst data by setting suitable ODIM metadata and geometry.
Definition: ProductOp.h:176
virtual void setGeometry(const MS &srcODIM, PlainData< dst_t > &dstData) const =0
Sets automagically the suitable dst parameters.
ProductOp(const std::string &name, const std::string &description)
Default constructor.
Definition: ProductOp.h:91
Definition: QuantityMap.h:50
bool setQuantityDefaults(EncodingODIM &dst, const std::string &quantity, const std::string &values="") const
Sets default values of given quantity - but not the quantity itself. Optionally overrides with user v...
Definition: QuantityMap.cpp:398
Namespace for images and image processing tools.
Definition: AccumulationArray.cpp:45
Definition: DataSelector.cpp:44
Writable data type.
Definition: Data.h:122
Read-only data type.
Definition: Data.h:112