Pusher.hh 10.4 KB
/*
 * Pusher.h
 *
 *  Created on: Dec 10, 2012
 *      Author: f.casimir
 */

#ifndef PUSHER_H_
#define PUSHER_H_

#include <vector>
#include "ParamData.hh"


#include "DD.hh"

namespace AMDA {
namespace Parameters {

namespace Base {
	/**
	 * @class Pusher
	 * @details This class is the operation responsible to transform raw data from DDServer into a ParamData
	 * of the corresponding type ( scalar or vector or Tab2D of short or int or float or double or ... type).
	 */
	struct Pusher {
		Pusher (int maxDim1Size=1,int maxDim2Size=1) : _maxDim1Size(maxDim1Size), _maxDim2Size(maxDim2Size), _paramData(NULL), _fillValue(NAN) {}
		virtual ~Pusher() {}
		virtual void put(DD_data_t *data) = 0;
		virtual void putNaN() = 0;
		void setFillValue(double pFillValue) {
			_fillValue = pFillValue;
		}
		double getFillValue() {
			return _fillValue;
		}
		int _maxDim1Size; /*!< Used for vector and Tab2D */
		int _maxDim2Size; /*!< Used for Tab2D */
		ParamData* _paramData; /*!< return ParamData to a Process*/
	protected:
		float _fillValue; /*!< When this value is different of NAN, into the raw data, it is replaced by NAN into ParamData. */
	};
}

//#define DD_SHORT 4
//#define DD_INT     1
//#define DD_FLOAT   2
//#define DD_DOUBLE 3
//#define DD_CHAR   0

typedef enum {
	CT_UNKNOWN,
	CT_SCALAR,
	CT_TAB1D,
	CT_TAB2D
} ContainerType;

template <int type>
struct MapType { typedef void Type; };

template <> struct MapType<4> {	typedef short Type; };
template <> struct MapType<1> {	typedef int Type; };
template <> struct MapType<2> {	typedef float Type; };
template <> struct MapType<3> {	typedef double Type;  };
template <> struct MapType<0> {	typedef char Type; };



template<int type,ContainerType container = CT_SCALAR>
class Pusher;

/**
 * @brief Pusher implementation for the CT_TAB2D.
 */
template<int type>
class Pusher<type,CT_TAB2D> : public Base::Pusher {
public:
	typedef typename MapType<type>::Type BaseElemenType;
	typedef Tab2DData<BaseElemenType> ElemenType;
	typedef ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	Pusher(int maxDim1Size, int maxDim2Size, int maxDim3Size, int dim1Num = 0, int dim2Num = 1, int dim3Num = -1, int dim3CutIndex = -1, int minSumIndex=-1, int maxSumIndex=-1) : Base::Pusher(maxDim1Size,maxDim2Size), _maxDim3Size(maxDim3Size), _dim1Num(dim1Num), _dim2Num(dim2Num), _dim3Num(dim3Num), _dim3CutIndex(dim3CutIndex),_minSumIndex(minSumIndex), _maxSumIndex(maxSumIndex) {
		_paramData = _specParamData = createParamData();
	}

	void put(DD_data_t *data) {
		BaseElemenType **lData = reinterpret_cast<BaseElemenType **>(data->Variables);

		//ParamData is created, add data
		_specParamData->getDataList().resize(data->VarNumber);
                            
		

                              if(_dim3CutIndex == -1 && _minSumIndex != -1 && _maxSumIndex != -1){
                                         for (int index = 0; index < data->VarNumber; index++) {
			ElemenType elem = ElemenType(_maxDim1Size,_maxDim2Size);
			elem << NotANumber();
			for (int dim1Index= 0; dim1Index < data->Dimensions[_dim1Num]; ++dim1Index)
			{
				for (int dim2Index= 0; dim2Index < data->Dimensions[_dim2Num]; ++dim2Index)
				{   
                                        BaseElemenType cumulatedElement;
                                        cumulatedElement << NotANumber() ;
                                                                                         for(int sumIndex=_minSumIndex; sumIndex <= _maxSumIndex; ++sumIndex){
					int dataIndex = 0;
					if (_dim3Num >= 0 && _dim3Num < 3 && data->DimNumber == 3) {
						int curentIndex = (sumIndex >= 0 && sumIndex < data->Dimensions[_dim3Num]) ? sumIndex : 0;
						if (_dim3Num == 0) {
							dataIndex = curentIndex*data->Dimensions[_dim1Num]*data->Dimensions[_dim2Num] + dim1Index*data->Dimensions[_dim2Num] + dim2Index;
						}
						else if (_dim3Num == 1) {
							dataIndex = dim1Index*data->Dimensions[_dim2Num]*data->Dimensions[_dim3Num] + curentIndex*data->Dimensions[_dim2Num] + dim2Index;
						}
						else {
							dataIndex = dim1Index*data->Dimensions[_dim1Num]*data->Dimensions[_dim2Num] + dim2Index*data->Dimensions[_dim1Num] + curentIndex;
						}
					}
					else {
						dataIndex = dim1Index*data->Dimensions[_dim2Num]+dim2Index;
					}
					BaseElemenType  baseElem =  lData[index][dataIndex];
					if (!isnan(_fillValue))
					{
						double crt_val = baseElem;
						bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue);
						if(is_fill_value)
							baseElem << NotANumber();
					}
                                        if (!isNAN(baseElem)) {
                                                if (isNAN(cumulatedElement))
                                                    cumulatedElement << ElemNull();
                                                cumulatedElement += baseElem;
                                        }
                                 }
                                 elem[dim1Index][dim2Index] = cumulatedElement;
                                                                                                    }
					
				}
                                                                 _specParamData->getDataList().push_back(elem);
			}
                                  
			
		
                              }else{
                                  for (int index = 0; index < data->VarNumber; index++) {
			ElemenType elem = ElemenType(_maxDim1Size,_maxDim2Size);
			elem << NotANumber();
			for (int dim1Index= 0; dim1Index < data->Dimensions[_dim1Num]; ++dim1Index)
			{
				for (int dim2Index= 0; dim2Index < data->Dimensions[_dim2Num]; ++dim2Index)
				{
					int dataIndex = 0;
					if (_dim3Num >= 0 && _dim3Num < 3 && data->DimNumber == 3) {
						int cutIndex = (_dim3CutIndex >= 0 && _dim3CutIndex < data->Dimensions[_dim3Num]) ? _dim3CutIndex : 0;
						if (_dim3Num == 0) {
							dataIndex = cutIndex*data->Dimensions[_dim1Num]*data->Dimensions[_dim2Num] + dim1Index*data->Dimensions[_dim2Num] + dim2Index;
						}
						else if (_dim3Num == 1) {
							dataIndex = dim1Index*data->Dimensions[_dim2Num]*data->Dimensions[_dim3Num] + cutIndex*data->Dimensions[_dim2Num] + dim2Index;
						}
						else {
							dataIndex = dim1Index*data->Dimensions[_dim1Num]*data->Dimensions[_dim2Num] + dim2Index*data->Dimensions[_dim1Num] + cutIndex;
						}
					}
					else {
						dataIndex = dim1Index*data->Dimensions[_dim2Num]+dim2Index;
					}
					BaseElemenType baseElem = lData[index][dataIndex];
					if (!isnan(_fillValue))
					{
						double crt_val = baseElem;
						bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue);
						if(is_fill_value)
							baseElem << NotANumber();
					}
					elem[dim1Index][dim2Index] = baseElem;
				}
			}
			_specParamData->getDataList().push_back(elem);
		}
	}
        }

	void putNaN() {
		_specParamData->getDataList().resize(1);
		ElemenType nanElem = ElemenType(_maxDim1Size,_maxDim2Size);
		for(int i = 0; i < _maxDim1Size; ++i) {
			for(int j = 0; j < _maxDim2Size; ++j) {
				nanElem[i][j] << NotANumber();
			}
		}
		_specParamData->getDataList().push_back(nanElem);
	}

	SpecParamData* createParamData() {
		return new ParamDataSpec< Tab2DData<typename MapType<type>::Type> >(_maxDim1Size,_maxDim2Size);
	}

private:

	int _maxDim3Size;

	int _dim1Num;

	int _dim2Num;

	int _dim3Num;

	int _dim3CutIndex;
        
                   int _minSumIndex;
    
                    int _maxSumIndex;
};

/**
 * @brief Pusher implementation for the CT_TAB1D.
 */
template<int type>
class Pusher<type,CT_TAB1D> : public Base::Pusher {
public:
	typedef typename MapType<type>::Type BaseElemenType;
	typedef std::vector<BaseElemenType> ElemenType;
	typedef ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	Pusher(int maxDimSize) : Base::Pusher(maxDimSize) {
		_paramData = _specParamData = createParamData();
	}

	void put(DD_data_t *data) {
		BaseElemenType **lData = reinterpret_cast<BaseElemenType **>(data->Variables);

		//ParamData is created, add data
		_specParamData->getDataList().resize(data->VarNumber);

		for (int index = 0; index < data->VarNumber; index++) {
			ElemenType elem = ElemenType();
			elem.resize(_maxDim1Size);
			elem << NotANumber();
			std::copy (lData[index], lData[index] + data->Dimensions[0], elem.begin());
			if(!isnan(_fillValue)) {
				for(auto it = elem.begin(); it != elem.end(); ++it) {
					double crt_val = *it;
					bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue);
					if(is_fill_value) {
						*it << NotANumber();
					}
				}
			}
			_specParamData->getDataList().push_back(elem);
		}
	}

	void putNaN() {
		_specParamData->getDataList().resize(1);
		ElemenType nanElem = ElemenType();
		nanElem.resize(_maxDim1Size);
		nanElem << NotANumber();
		_specParamData->getDataList().push_back(nanElem);
	}

	SpecParamData* createParamData() {
		return new ParamDataSpec< std::vector<typename MapType<type>::Type> >(_maxDim1Size);
	}

};


/**
 * @brief Pusher implementation for the scalar.
 */
template<int type>
class Pusher<type,CT_SCALAR> : public Base::Pusher {
public:
	typedef typename MapType<type>::Type BaseElemenType;
	typedef BaseElemenType ElemenType;
	typedef ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	/**
	 * @brief Constructor
	 * @details Create the real ParamData.
	 */
	Pusher() : Base::Pusher() {
		_paramData = _specParamData = createParamData();
	}

	void put(DD_data_t *data) {
		BaseElemenType **lData = reinterpret_cast<BaseElemenType **>(data->Variables);

		//ParamData is created, add data
		_specParamData->getDataList().resize(data->VarNumber);

                BaseElemenType nanElem;
                nanElem << NotANumber();

		if(!isnan(_fillValue)) {
                        BaseElemenType nanElem;
                        nanElem << NotANumber();
			for (int index = 0; index < data->VarNumber; index++) {
				double crt_val = *lData[index];
				bool is_fill_value = isApproximatelyEqual(crt_val, _fillValue);
				if(!is_fill_value) {
					_specParamData->getDataList().push_back(*lData[index]);
				} else {
					_specParamData->getDataList().push_back(nanElem);
				}
			}
		}
		else {
			for (int index = 0; index < data->VarNumber; index++) {
				_specParamData->getDataList().push_back(*lData[index]);
			}

		}
	}

	void putNaN() {
                BaseElemenType nanElem;
                nanElem << NotANumber();
		_specParamData->getDataList().resize(1);
		_specParamData->getDataList().push_back(nanElem);
	}

	SpecParamData* createParamData() {
		return new SpecParamData();
	}
};

} /* namespace Parameters */
} /* namespace AMDA */
#endif /* PUSHER_H_ */