SumIntoTableRange.hh 10.5 KB
/*
 * SumIntoTableRange.hh
 *
 *  Created on: Oct 6, 2016
 *      Author: AKKA IS
 */

#ifndef SUMINTOTABLERANGE_HH_
#define SUMINTOTABLERANGE_HH_

#include "Parameter.hh"
#include "ParamData.hh"
#include "DataTypeMath.hh"
#include "Operation.hh"

namespace AMDA {
namespace Parameters {
namespace SumIntoTableRange {

namespace Base {
class TableDataTransform {
public:
	virtual ~TableDataTransform() {}
	virtual std::vector<double>  transformData(unsigned int /*index*/) = 0;
};
}

template<typename ParamInput>
class TableDataTransform : public Base::TableDataTransform {
public:

	/**
	 * @brief Constructor
	 */
	TableDataTransform(ParamInput&  pParamInput) : _paramInput(pParamInput) {}

private:
	/**
	 * @brief paramData Input
	 */
	ParamInput&  _paramInput;
};

template<typename ElType>
class TableDataTransform<ParamDataSpec<std::vector<ElType> >> : public Base::TableDataTransform {
public:
	typedef	ParamDataSpec<std::vector<ElType> > ParamInput;

	/**
	 * @brief Constructor
	 */
	TableDataTransform(ParamInput&  pParamInput) : _paramInput(pParamInput) {}

	/**
	 * @overload Base::TableDataTransform::transformData(unsigned int index)
	 */
	std::vector<double>  transformData(unsigned int index) {
		const std::vector<ElType>& lData = _paramInput.getDataList()[index];
		std::vector<double> transData;
		for (typename std::vector<ElType>::const_iterator it = lData.begin(); it != lData.end(); ++it) {
			transData.push_back((double)*it);
		}
		return transData;
	}

private:
	ParamInput&  _paramInput;
};



class TableParamDataVisitor : public VisitorOfParamData {
public:
	/**
	 * @brief Constructor.
	 */
	TableParamDataVisitor(ParamData& pInputParamData) : _dataTransform(NULL) {
		pInputParamData.accept(*this);
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataScalaireShort *)
	 */
	void visit(ParamDataScalaireShort *) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported")); }

	/**
	 * @overload VisitorOfParamData::visit(ParamDataScalaireFloat *)
	 */
	void visit(ParamDataScalaireFloat *) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported")); }

	/**
	 * @overload VisitorOfParamData::visit(ParamDataScalaireDouble *)
	 */
	void visit(ParamDataScalaireDouble *) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported")); }

	/**
	 * @overload VisitorOfParamData::visit(ParamDataScalaireLongDouble *)
	 */
	void visit(ParamDataScalaireLongDouble *) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported")); }

	/**
	 * @overload VisitorOfParamData::visit(ParamDataScalaireInt *)
	 */
	void visit(ParamDataScalaireInt *) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported")); }

	/**
	 * @overload VisitorOfParamData::visit(ParamDataLogicalData *)
	 */
	void visit(ParamDataLogicalData *) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported")); }

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab1DShort *)
	 */
	void visit(ParamDataTab1DShort *pInputParamData) {
		_dataTransform = new TableDataTransform<ParamDataTab1DShort>(*pInputParamData);
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab1DFloat *)
	 */
	void visit(ParamDataTab1DFloat *pInputParamData) {
		_dataTransform = new TableDataTransform<ParamDataTab1DFloat>(*pInputParamData);
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab1DDouble *)
	 */
	void visit(ParamDataTab1DDouble *pInputParamData) {
		_dataTransform = new TableDataTransform<ParamDataTab1DDouble>(*pInputParamData);
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab1DLongDouble *)
	 */
	void visit(ParamDataTab1DLongDouble *pInputParamData) {
		_dataTransform = new TableDataTransform<ParamDataTab1DLongDouble>(*pInputParamData);
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab1DInt *)
	 */
	void visit(ParamDataTab1DInt *pInputParamData) {
		_dataTransform = new TableDataTransform<ParamDataTab1DInt>(*pInputParamData);
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab1DLogicalData *)
	 */
	void visit(ParamDataTab1DLogicalData *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab2DShort *)
	 */
	void visit(ParamDataTab2DShort *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab2DFloat *)
	 */
	void visit(ParamDataTab2DFloat *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab2DDouble *)
	 */
	void visit(ParamDataTab2DDouble *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab2DLongDouble *)
	 */
	void visit(ParamDataTab2DLongDouble *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab2DInt *)
	 */
	void visit(ParamDataTab2DInt *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));
	}

	/**
	 * @overload VisitorOfParamData::visit(ParamDataTab2DLogicalData *)
	 */
	void visit(ParamDataTab2DLogicalData *) {
		BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("TableParamDataPusher operation not supported"));
	}

	/**
	 * @brief get the Deriv parameterized operation.
	 */
	std::vector<double> transformData(unsigned int index) {

		return _dataTransform->transformData(index);
	}

private:
	Base::TableDataTransform* _dataTransform;
};

/**
 * @class SumIntoTableRange
 * @brief It is responsible to compute the sum of parameter data into a table range.
 * @details This class implement the interface Operation.
 */
template<typename DataType>
class SumIntoTableRange : public Operation {

public:
	/**
	 * @brief Constructor.
	 * @details Create the ParamData type of the input ParamData.
	 */
	SumIntoTableRange(Process& pProcess, ParamDataSpec<std::vector<DataType> >& paramInput, double minRange, double maxRange, AMDA::Info::ParamTable* tablePtr)
	: Operation(pProcess),
	  _paramInput(paramInput),
	  _paramOutput(new ParamDataSpec<DataType>()),
	  _minRange(minRange),
	  _maxRange(maxRange),
	  _tablePtr(tablePtr) {
	  _paramDataOutput=_paramOutput;
	}

	virtual ~SumIntoTableRange() {
		for (std::map<std::string, TableParamDataVisitor*>::iterator it = _tableParamDataVisitor.begin(); it != _tableParamDataVisitor.end(); ++it)
			delete it->second;
		_tableParamDataVisitor.clear();
	}

	/**
	 * @overload Operation::write(ParamDataIndexInfo &pParamDataIndexInfo)
	 */
  void  write(ParamDataIndexInfo &pParamDataIndexInfo) {
	  for (unsigned int _index = pParamDataIndexInfo._startIndex ;
			  _index < pParamDataIndexInfo._startIndex + pParamDataIndexInfo._nbDataToProcess;
			  ++_index)
	  {
		  double crtTime = _paramInput.getTime(_index);
		  std::vector<DataType> inputElt = _paramInput.get(_index);

		  //Get list of indexes included in the range
		  std::list<unsigned int> _indexes;
		  if (!_tablePtr->isVariable()) {

			  AMDA::Info::t_TableBound crtBound;

			  for (unsigned int i = 0; i < inputElt.size(); ++i) {
				  crtBound = _tablePtr->getBound(&_process.getParameterManager(), i);

				  if (crtBound.min >= _minRange && crtBound.max <= _maxRange)
					  _indexes.push_back(i);
			  }
		  }
		  else
		  {
			  //Variable table
			   std::map<std::string, std::vector<double>> paramsTableData;
			  for (std::map<std::string, std::string>::iterator it = _tablePtr->getTableParams().begin(); it != _tablePtr->getTableParams().end(); ++it) {
				  ParameterSPtr crtParam = _process.getParameterManager().getParameter(it->second);
				  ParamData* ltableParamInput = crtParam->getParamData(&_process).get();

				  //Retrieve related index for this "table" parameter
				  unsigned int crtTimeTableParamIndex = ltableParamInput->getIndexInfo()._startIndex;
				  for (unsigned int tableParamindex = ltableParamInput->getIndexInfo()._startIndex ;
						  tableParamindex < ltableParamInput->getIndexInfo()._startIndex + ltableParamInput->getIndexInfo()._nbDataToProcess;
						  ++tableParamindex) {
					  if (crtTime < ltableParamInput->getTime(tableParamindex))
						  break;
					  crtTimeTableParamIndex = tableParamindex;
				  }

				  if (_tableParamDataVisitor.find(it->first) == _tableParamDataVisitor.end()) {
					  _tableParamDataVisitor[it->first] = new TableParamDataVisitor(*ltableParamInput);
				  }

				  paramsTableData[it->first] = _tableParamDataVisitor[it->first]->transformData(crtTimeTableParamIndex);
			  }

			  AMDA::Info::t_TableBound crtBound;

			  for (unsigned int i = 0; i < inputElt.size(); ++i) {

				  crtBound = _tablePtr->getBound(&_process.getParameterManager(), i, &paramsTableData);

  				  if ((crtBound.min >= _minRange) && (crtBound.max <= _maxRange)) {
  					  _indexes.push_back(i);
  				  }
		  	  }

		  }

		  DataType output = 0;

		  for (std::list<unsigned int>::iterator it = _indexes.begin(); it != _indexes.end(); ++it) {
			  if (isNAN(inputElt[*it]))
				  continue;
			  output += inputElt[*it];
		  }

		  _paramOutput->pushTime(crtTime);
		  _paramOutput->getDataList().push_back(output);
	  }
  }

private:
	/**<
	 * @brief It is the channel of data derived
	 */
  ParamDataSpec<std::vector<DataType> > &_paramInput;

	/**<
	 * @brief It is the channel of the data derived
	 */
  ParamDataSpec<DataType> *_paramOutput;

  double _minRange;

  double _maxRange;

  AMDA::Info::ParamTable* _tablePtr;

  std::map<std::string, TableParamDataVisitor*> _tableParamDataVisitor;
};

} /* namespace SumIntoTableRange */
} /* namespace Parameters */
} /* namespace AMDA */
#endif /* SUMINTOTABLERANGE_HH_ */