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.debug3(*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  dst["what"] = src["what"];
382  dst["where"] = src["where"];
383  dst["how"] = src["how"];
384  dst["what"].data.attributes["object"] = this->odim.object;
385  // odim.copyToRoot(dst); NO! Mainly overwrites original data. fgrep 'declare(rootAttribute' odim/*.cpp
386 
387  //ODIMPath dataSetPath;
388  ODIMPathElem parent(ODIMPathElem::DATASET, 1); // /dataset1
389  ODIMPathElem child(ODIMPathElem::DATA, 1); // /dataset1
390 
391  mout.note("appendResults path: " , ProductBase::appendResults );
393  ODIMPathTools::getNextChild(dst, parent);
394  }
395 
396  ODIMPathTools::getNextChild(dst[parent], child);
397 
398  mout.note("storing product in path: " , parent , '|' , child );
399  //mout.debug3("storing product in path: " , dataSetPath );
400 
401  Hi5Tree & dstProduct = dst[parent][child]; // (dataSetPath);
402  DataSet<dst_t> dstProductDataset(dstProduct); // PATH
403 
404 
406  this->computeSingleProduct(sweeps, dstProductDataset);
407 
408  ProductBase::setRackVersion(dstProduct["how"].data.attributes);
409  //drain::VariableMap & how = dstProduct["how"].data.attributes;
410  //how["software"] = __RACK__;
411  //how["sw_version"] = __RACK_VERSION__;
412  // how["elangles"] = elangles; // This service could be lower in hierarchy (but for PseudoRHI and pCappi ok here)
413 
414  //DataTools::updateInternalAttributes(dstProduct);
415  //drain::VariableMap & what = dst[dataSetPath]["what"].data.attributes;
416  //what["source"] = src["what"].data.attributes["source"];
417  //what["object"] = odim.object;
418 
419 }
420 
421 
422 //template <class M>
423 template <class MS, class MD>
425 
426  drain::Logger mout(__FILE__, __FUNCTION__); //REPL this->name+"(VolumeOp<M>)", __FUNCTION__);
427  mout.debug3("start" );
428 
429  if (src.size() == 0)
430  mout.warn("no data" );
431 
432  //for (typename DataSetMap<src_t >::const_iterator it = src.begin(); it != src.end(); ++it) {
433  for (const auto & entry: src) {
434  mout.debug3("calling processDataSet for elev=", entry.first, " #datasets=", entry.second.size());
435  processDataSet(entry.second, dstProduct);
436  // TODO: detect first init?
437  // mout.warn("OK" );
438  }
439 
441  // mout.warn("getFirst data" );
442  //@ Data<DstType<MD> > & dstData = dstProduct.getFirstData(); // main data
443  //@ dstProduct.updateTree(dstData.odim);
444  // mout.warn("end" );
445 }
446 
447 
448 //template <class M>
449 template <class MS, class MD>
450 void ProductOp<MS,MD>::processDataSet(const DataSet<src_t > & srcSweep, DataSet<DstType<MD> > & dstProduct) const {
451 
452  //drain::Logger mout(__FILE__, __FUNCTION__); //REPL this->name+"(ProductOp<MS,MD>)", __FUNCTION__);
453  drain::Logger mout(__FILE__, __FUNCTION__);
454 
455  mout.debug("start" );
456 
457  const Data<src_t > & srcData = srcSweep.getFirstData();
458 
459  mout.debug("target quantity: " , odim.quantity );
460 
461  // NEW 2020/06
462  const std::string & quantity = !odim.quantity.empty() ? odim.quantity : srcData.odim.quantity;
463  Data<DstType<MD> > & dstData = dstProduct.getData(quantity);
464  dstData.odim.quantity = quantity;
465 
466  // OLD
467  // Data<DstType<MD> > & dstData = !odim.quantity.empty() ? dstProduct.getData(odim.quantity) : dstProduct.getFirstData();
468  //if (dstData.odim.quantity.empty())
469  // dstData.odim.quantity = odim.quantity;
470 
471  //mout.debug("calling setEncoding" );
472  //setEncoding(srcData.odim, dstData.odim);
473  this->initDst(srcData.odim, dstData);
474 
475  //mout.warn("calling processData" );
476  processData(srcData, dstData);
477  //mout.warn("updateTree" );
478  //@ dstData.updateTree();
479 }
480 
481 
482 
483 
484 
485 } // namespace rack
486 
487 
488 #endif /* RACKOP_H_ */
489 
490 // Rack
491  // REP
492  // 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:308
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition: Log.h:507
Logger & note(const TT &... args)
For top-level information.
Definition: Log.h:485
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
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 DATASET
First level group, /dataset + digit .
Definition: ODIMPath.h:103
static const group_t DATA
Second level group, /data + digit .
Definition: ODIMPath.h:106
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:92
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