AbstractFunc.hh 8.68 KB
/*
 * AbstractFunc.hh
 *
 *  Created on: Jun 21, 2018
 *      Author: benjamin
 */

#ifndef ABSTRACTFUNC_HH_
#define ABSTRACTFUNC_HH_

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

#include <iterator>

namespace AMDA {
namespace Parameters {
namespace StatisticFunctions {

/**
 * @class AbstractFunc
 * @brief 
 * @details This class implement the interface Operation.
 */

class AbstractFuncBase : public Operation {
public:
	AbstractFuncBase(Process& pProcess, TimeIntervalListSPtr pTimeIntervalList, double windowtime) : Operation(pProcess), _timeIntervalList(pTimeIntervalList), _currentTimeInterval(pTimeIntervalList->begin()), _windowtime(windowtime), _needInit(true) {

	}

	virtual ~AbstractFuncBase() {

	}

	double getWindowTime() {
		return _windowtime;
	}

	bool inWindow(double time) {
		return (time >= _minWindow && time <= _maxWindow);
	}

	double getIntStartTime() {
		return _currentTimeInterval->_startTime;
	}

	double getIntStopTime() {
		return _currentTimeInterval->_stopTime;
	}

	bool inInt(double time) {
		return (time >= _currentTimeInterval->_startTime && time <= _currentTimeInterval->_stopTime);
	}

	double getTarget() {
		return _target;
	}

	bool needInit() {
		return _needInit;
	}

	void setNeedInit(bool needInit) {
		_needInit = needInit;
	}

	bool setTarget(double time) {
		if (!inInt(time)) {
			return false;
		}

		_target = time;
		_minWindow = _target - _windowtime / 2.;
		if (_minWindow < _currentTimeInterval->_startTime) {
			_minWindow = _currentTimeInterval->_startTime;
		}
		_maxWindow = _target + _windowtime / 2.;
		if (_maxWindow > _currentTimeInterval->_stopTime) {
			_maxWindow = _currentTimeInterval->_stopTime;
		}
		return true;
	}

	/**
	 * @overload Operation::reset(double pStartTime, double pTimeInt)
	 * @brief reset static data to process another TimeInterval
	 */
	virtual void reset() {
		Operation::reset();
		if (_currentTimeInterval == _timeIntervalList->end()) {
			return;
		}
		++_currentTimeInterval;
		_needInit = true;
                resetFunc();
	}

	virtual bool nextTarget() = 0;

	virtual bool needToChangeTarget(double crtTime) = 0;

	virtual double getSampling() = 0;

	virtual void init() = 0;
        
        virtual void resetFunc() = 0;

private:
	TimeIntervalListSPtr _timeIntervalList;

	TimeIntervalList::iterator _currentTimeInterval;

	double _windowtime;

	double _minWindow;

	double _maxWindow;

	double _target;

	bool _needInit;
};

template <typename InputElemType, typename OutputElemType> 
class AbstractFunc : public AbstractFuncBase {
public:
	/**
	 * @brief Constructor.
	 * @details Create the ParamData type of the input ParamData.
	 */
	AbstractFunc(Process& pProcess, TimeIntervalListSPtr pTimeIntervalList, ParamDataSpec<InputElemType>& paramInput, double windowtime)
	: AbstractFuncBase(pProcess, pTimeIntervalList, windowtime),
	  _paramInput(paramInput),
	  _paramOutput(new ParamDataSpec<OutputElemType>) {
	  _paramDataOutput=_paramOutput;
	}

	virtual ~AbstractFunc() {
	}

	virtual void pushData(double time, InputElemType& elem) = 0;

	virtual OutputElemType compute() = 0;
        
	/**
	 * @overload Operation::write(ParamDataIndexInfo &pParamDataIndexInfo)
	 */
  
	void write(ParamDataIndexInfo &pParamDataIndexInfo) {
		if ((pParamDataIndexInfo._nbDataToProcess > 0)) {
			if (pParamDataIndexInfo._startIndex == 0) {
				_nanVal = _paramInput.get(0);
				_nanVal << NotANumber();
			}
                        for (unsigned int _index = pParamDataIndexInfo._startIndex ;
				_index < pParamDataIndexInfo._startIndex + pParamDataIndexInfo._nbDataToProcess;
				++_index)
			{
				double crtTime = _paramInput.getTime(_index);
                                InputElemType crtVal = _paramInput.get(_index);
                                if (needToChangeTarget(crtTime)) {
                                    _paramOutput->pushTime(getTarget());
                                    _paramOutput->push(compute());
                                    pushData(crtTime, crtVal);
                                    nextTarget();
                                    bool skip = false;
                                    while (!skip && needToChangeTarget(crtTime)) {
                                        _paramOutput->pushTime(getTarget());
                                        _paramOutput->push(compute());
                                        skip = nextTarget();
                                    }
                                }
                                else {
                                    pushData(crtTime, crtVal);
                                    if (needInit()) {
					init();
                                    }
                                }
			}
		}
		if (pParamDataIndexInfo._timeIntToProcessChanged || pParamDataIndexInfo._noMoreTimeInt) {
                    if (!needInit()) {
			do {
                            if (inInt(getTarget())) {
				_paramOutput->pushTime(getTarget());
				_paramOutput->push(compute());
                            }
			} while (nextTarget());
                    }
		}
	}

	double getInputParamSampling() {
		return _paramInput.getMinSampling();
	}

private:
	ParamDataSpec<InputElemType>& _paramInput;

	ParamDataSpec<OutputElemType>* _paramOutput;

protected:
	OutputElemType _nanVal;
};  

template <typename InputElemType, typename OutputElemType>
class ClassicAbstractFunc : public AbstractFunc<InputElemType,OutputElemType> {
public:
	ClassicAbstractFunc(Process& pProcess, TimeIntervalListSPtr pTimeIntervalList, ParamDataSpec<InputElemType>& paramInput, double windowtime)
          : AbstractFunc<InputElemType,OutputElemType>(pProcess, pTimeIntervalList, paramInput, windowtime) {
	}

	virtual ~ClassicAbstractFunc() {
	}

	virtual void init() {
		AbstractFunc<InputElemType,OutputElemType>::setTarget(AbstractFunc<InputElemType,OutputElemType>::getIntStartTime());
		AbstractFunc<InputElemType,OutputElemType>::setNeedInit(false);
	}

	virtual bool nextTarget() {
		double target = AbstractFunc<InputElemType,OutputElemType>::getTarget() + AbstractFunc<InputElemType,OutputElemType>::getWindowTime();
                bool res = AbstractFunc<InputElemType,OutputElemType>::setTarget(target);
                while (!_mem.empty() && !AbstractFunc<InputElemType,OutputElemType>::inWindow(_mem.front().first)) {
                    _mem.pop_front();
                }
                return res;
	}

	virtual bool needToChangeTarget(double crtTime) {
		return !AbstractFunc<InputElemType,OutputElemType>::needInit() && !AbstractFunc<InputElemType,OutputElemType>::inWindow(crtTime);
	}

	virtual double getSampling() {
		return AbstractFunc<InputElemType,OutputElemType>::getWindowTime();
	}

	virtual void pushData(double time, InputElemType& elem) {
		_mem.push_back(std::make_pair(time, elem));
	}
        
        virtual void resetFunc() {
            _mem.clear();
        }

protected:
	std::list<std::pair<double,InputElemType> > _mem;
};

template <typename InputElemType, typename OutputElemType>
class SmAbstractFunc : public AbstractFunc<InputElemType,OutputElemType> {
public:
	SmAbstractFunc(Process& pProcess, TimeIntervalListSPtr pTimeIntervalList, ParamDataSpec<InputElemType>& paramInput, double windowtime)
	  : AbstractFunc<InputElemType,OutputElemType>(pProcess, pTimeIntervalList, paramInput, windowtime) {
	}

	virtual ~SmAbstractFunc() {
	}

	virtual void init() {
            if (!_targets.empty()) {
		AbstractFunc<InputElemType,OutputElemType>::setTarget(_targets.front());
                AbstractFunc<InputElemType,OutputElemType>::setNeedInit(false);
                _targets.pop_front();
            }
	}

	virtual bool nextTarget() {
		if (!_targets.empty()) {
			bool res = AbstractFunc<InputElemType,OutputElemType>::setTarget(_targets.front());
			_targets.pop_front();
                        while (!_mem.empty() && !AbstractFunc<InputElemType,OutputElemType>::inWindow(_mem.front().first)) {
                            _mem.pop_front();
                        }
			return res;
		}
		return false;
	}

	virtual bool needToChangeTarget(double crtTime) {
		return !AbstractFunc<InputElemType,OutputElemType>::needInit() && !AbstractFunc<InputElemType,OutputElemType>::inWindow(crtTime) && !_targets.empty() ;
	}

	virtual double getSampling() {
		return AbstractFunc<InputElemType,OutputElemType>::getInputParamSampling();
	}

	virtual void pushData(double time, InputElemType& elem) {
		_mem.push_back(std::make_pair(time, elem));
		_targets.push_back(time);
	}
        
        virtual void resetFunc() {
            _mem.clear();
            _targets.clear();
        }

protected:
	std::list<double> _targets;

	std::list<std::pair<double,OutputElemType> > _mem;
};

} /* namespace StatisticFunctions */
} /* namespace Parameters */
} /* namespace AMDA */
#endif /* ABSTRACTFUNC_HH_ */